Merge pull request #15693 from johngmyers/v1alpha3-config

v1alpha3: move state store location config under its own sub-struct
This commit is contained in:
Kubernetes Prow Robot 2023-07-24 22:04:04 -07:00 committed by GitHub
commit c78c38e70f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 231 additions and 106 deletions

View File

@ -115,7 +115,7 @@ func serverVersion(f *util.Factory, options *VersionOptions) string {
if err != nil {
return "could not fetch cluster"
}
configBase, err := f.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase)
configBase, err := f.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return "could not talk to vfs"
}

View File

@ -1607,6 +1607,7 @@ the removal of fields no longer in use.
| cloudConfig.spotinstOrientation | cloudProvider.aws.spotinstOrientation |
| cloudConfig.spotinstProduct | cloudProvider.aws.spotinstProduct |
| cloudProvider (string) | cloudProvider (map) |
| configBase | configStore.base |
| DisableSubnetTags | tagSubnets (value inverted) |
| egressProxy | networking.egressProxy |
| etcdClusters[\*].etcdMembers[\*].kmsKeyId | etcdClusters[\*].etcdMembers[\*].kmsKeyID |
@ -1615,6 +1616,7 @@ the removal of fields no longer in use.
| externalDns.disable: true | externalDNS.provider: none |
| hooks[\*].disabled | hooks[\*].enabled (value inverted) |
| isolateMasters | networking.isolateControlPlane |
| keyStore | configStore.keypairs |
| kubeAPIServer.authorizationRbacSuperUser | kubeAPIServer.authorizationRBACSuperUser |
| kubeAPIServer.authorizationWebhookCacheAuthorizedTtl | kubeAPIServer.authorizationWebhookCacheAuthorizedTTL |
| kubeAPIServer.authorizationWebhookCacheUnauthorizedTtl | kubeAPIServer.authorizationWebhookCacheUnauthorizedTTL |
@ -1652,6 +1654,7 @@ the removal of fields no longer in use.
| podCIDR | networking.podCIDR |
| podIdentityWebhook | cloudProvider.aws.podIdentityWebhook |
| project | cloudProvider.gce.project |
| secretStore | configStore.secrets |
| serviceClusterIPRange | networking.serviceClusterIPRange |
| subnets | networking.subnets |
| tagSubnets | networking.tagSubnets |

View File

@ -40,7 +40,9 @@ func up(vfsContext *vfs.VFSContext, ctx context.Context) error {
CloudProvider: api.CloudProviderSpec{
AWS: &api.AWSSpec{},
},
ConfigBase: registryBase.Join(cluster.ObjectMeta.Name).Path(),
ConfigStore: api.ConfigStoreSpec{
Base: registryBase.Join(cluster.ObjectMeta.Name).Path(),
},
}
for _, z := range nodeZones {

View File

@ -62,9 +62,9 @@ func (s *s3PublicAclStrategy) GetACL(ctx context.Context, p vfs.Path, cluster *k
return nil, nil
}
config, err := url.Parse(cluster.Spec.ConfigBase)
config, err := url.Parse(cluster.Spec.ConfigStore.Base)
if err != nil {
return "", fmt.Errorf("unable to parse: %q", cluster.Spec.ConfigBase)
return "", fmt.Errorf("unable to parse: %q", cluster.Spec.ConfigStore.Base)
}
// We are checking that the path defined is not the state store, if it is

View File

@ -36,7 +36,9 @@ func Test_Strategy(t *testing.T) {
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigBase: "s3://my_state_store/cluster",
ConfigStore: kops.ConfigStoreSpec{
Base: "s3://my_state_store/cluster",
},
Assets: &kops.AssetsSpec{
FileRepository: values.String("https://s3.amazonaws.com/test"),
},
@ -65,7 +67,9 @@ func Test_In_StateStore(t *testing.T) {
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigBase: "s3://my_state_store/cluster",
ConfigStore: kops.ConfigStoreSpec{
Base: "s3://my_state_store/cluster",
},
Assets: &kops.AssetsSpec{
FileRepository: values.String("https://s3.amazonaws.com/my_state_store/opps"),
},

View File

@ -55,11 +55,8 @@ type ClusterSpec struct {
Channel string `json:"channel,omitempty"`
// Additional addons that should be installed on the cluster
Addons []AddonSpec `json:"addons,omitempty"`
// ConfigBase is the path where we store configuration for the cluster
// This might be different than the location where the cluster spec itself is stored,
// both because this must be accessible to the cluster,
// and because it might be on a different cloud or storage system (etcd vs S3)
ConfigBase string `json:"configBase,omitempty"`
// ConfigStore configures the stores that nodes use to get their configuration.
ConfigStore ConfigStoreSpec `json:"configStore"`
// CloudProvider configures the cloud provider to use.
CloudProvider CloudProviderSpec `json:"cloudProvider,omitempty"`
// GossipConfig for the cluster assuming the use of gossip DNS
@ -68,10 +65,6 @@ type ClusterSpec struct {
ContainerRuntime string `json:"containerRuntime,omitempty"`
// The version of kubernetes to install (optional, and can be a "spec" like stable)
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
// SecretStore is the VFS path to where secrets are stored
SecretStore string `json:"secretStore,omitempty"`
// KeyStore is the VFS path to where SSL keys and certificates are stored
KeyStore string `json:"keyStore,omitempty"`
// DNSZone is the DNS zone we should use when configuring DNS
// This is because some clouds let us define a managed zone foo.bar, and then have
// kubernetes.dev.foo.bar, without needing to define dev.foo.bar as a hosted zone.
@ -168,6 +161,19 @@ type ClusterSpec struct {
Karpenter *KarpenterConfig `json:"karpenter,omitempty"`
}
// ConfigStoreSpec configures the stores that nodes use to get their configuration.
type ConfigStoreSpec struct {
// Base is the VFS path where we store configuration for the cluster
// This might be different than the location where the cluster spec itself is stored,
// both because this must be accessible to the cluster,
// and because it might be on a different cloud or storage system (etcd vs S3).
Base string `json:"base,omitempty"`
// Keypairs is the VFS path to where certificates and corresponding private keys are stored.
Keypairs string `json:"keypairs,omitempty"`
// Secrets is the VFS path to where secrets are stored.
Secrets string `json:"secrets,omitempty"`
}
// PodIdentityWebhookSpec configures an EKS Pod Identity Webhook.
type PodIdentityWebhookSpec struct {
Enabled bool `json:"enabled,omitempty"`

View File

@ -34,12 +34,12 @@ const (
)
func ConfigBase(vfsContext *vfs.VFSContext, c *api.Cluster) (vfs.Path, error) {
if c.Spec.ConfigBase == "" {
return nil, field.Required(field.NewPath("spec", "configBase"), "")
if c.Spec.ConfigStore.Base == "" {
return nil, field.Required(field.NewPath("spec", "configStore", "base"), "")
}
configBase, err := vfsContext.BuildVfsPath(c.Spec.ConfigBase)
configBase, err := vfsContext.BuildVfsPath(c.Spec.ConfigStore.Base)
if err != nil {
return nil, fmt.Errorf("error parsing ConfigBase %q: %v", c.Spec.ConfigBase, err)
return nil, fmt.Errorf("error parsing ConfigStore.Base %q: %v", c.Spec.ConfigStore.Base, err)
}
return configBase, nil
}

View File

@ -49,11 +49,13 @@ type ClusterSpec struct {
// The Channel we are following
Channel string `json:"channel,omitempty"`
// Additional addons that should be installed on the cluster
Addons []AddonSpec `json:"addons,omitempty"`
Addons []AddonSpec `json:"addons,omitempty"`
ConfigStore kops.ConfigStoreSpec `json:"-"`
// ConfigBase is the path where we store configuration for the cluster
// This might be different that the location when the cluster spec itself is stored,
// both because this must be accessible to the cluster,
// and because it might be on a different cloud or storage system (etcd vs S3)
// +k8s:conversion-gen=false
ConfigBase string `json:"configBase,omitempty"`
CloudProvider kops.CloudProviderSpec `json:"-"`
// The CloudProvider to use (aws or gce)
@ -96,12 +98,14 @@ type ClusterSpec struct {
// +k8s:conversion-gen=false
Topology *TopologySpec `json:"topology,omitempty"`
// SecretStore is the VFS path to where secrets are stored
// +k8s:conversion-gen=false
SecretStore string `json:"secretStore,omitempty"`
// KeyStore is the VFS path to where SSL keys and certificates are stored
// +k8s:conversion-gen=false
KeyStore string `json:"keyStore,omitempty"`
// ConfigStore is unused.
// +k8s:conversion-gen=false
ConfigStore string `json:"configStore,omitempty"`
LegacyConfigStore string `json:"configStore,omitempty"`
// DNSZone is the DNS zone we should use when configuring DNS
// This is because some clouds let us define a managed zone foo.bar, and then have
// kubernetes.dev.foo.bar, without needing to define dev.foo.bar as a hosted zone.

View File

@ -87,6 +87,7 @@ func Convert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *kops
out.AdditionalPolicies[k] = v
}
}
out.ConfigStore.Base = in.ConfigBase
if in.ExternalPolicies != nil {
policies := make(map[string][]string, len(in.ExternalPolicies))
for k, v := range in.ExternalPolicies {
@ -97,6 +98,8 @@ func Convert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *kops
}
out.ExternalPolicies = policies
}
out.ConfigStore.Secrets = in.SecretStore
out.ConfigStore.Keypairs = in.KeyStore
if in.KubeAPIServer != nil {
kube := in.KubeAPIServer
if kube.OIDCClientID != nil ||
@ -384,6 +387,9 @@ func Convert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec, out
kube.OIDCUsernameClaim = oidc.UsernameClaim
kube.OIDCUsernamePrefix = oidc.UsernamePrefix
}
out.ConfigBase = in.ConfigStore.Base
out.KeyStore = in.ConfigStore.Keypairs
out.SecretStore = in.ConfigStore.Secrets
if in.ExternalPolicies != nil {
out.ExternalPolicies = make(map[string][]string, len(in.ExternalPolicies))
for k, v := range in.ExternalPolicies {

View File

@ -2340,7 +2340,8 @@ func autoConvert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
} else {
out.Addons = nil
}
out.ConfigBase = in.ConfigBase
out.ConfigStore = in.ConfigStore
// INFO: in.ConfigBase opted out of conversion generation
out.CloudProvider = in.CloudProvider
// INFO: in.LegacyCloudProvider opted out of conversion generation
if in.GossipConfig != nil {
@ -2362,9 +2363,9 @@ func autoConvert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
// INFO: in.AdditionalNetworkCIDRs opted out of conversion generation
// INFO: in.NetworkID opted out of conversion generation
// INFO: in.Topology opted out of conversion generation
out.SecretStore = in.SecretStore
out.KeyStore = in.KeyStore
// INFO: in.ConfigStore opted out of conversion generation
// INFO: in.SecretStore opted out of conversion generation
// INFO: in.KeyStore opted out of conversion generation
// INFO: in.LegacyConfigStore opted out of conversion generation
out.DNSZone = in.DNSZone
if in.DNSControllerGossipConfig != nil {
in, out := &in.DNSControllerGossipConfig, &out.DNSControllerGossipConfig
@ -2698,7 +2699,7 @@ func autoConvert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec,
} else {
out.Addons = nil
}
out.ConfigBase = in.ConfigBase
out.ConfigStore = in.ConfigStore
out.CloudProvider = in.CloudProvider
if in.GossipConfig != nil {
in, out := &in.GossipConfig, &out.GossipConfig
@ -2711,8 +2712,6 @@ func autoConvert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec,
}
out.ContainerRuntime = in.ContainerRuntime
out.KubernetesVersion = in.KubernetesVersion
out.SecretStore = in.SecretStore
out.KeyStore = in.KeyStore
out.DNSZone = in.DNSZone
if in.DNSControllerGossipConfig != nil {
in, out := &in.DNSControllerGossipConfig, &out.DNSControllerGossipConfig

View File

@ -1033,6 +1033,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = make([]AddonSpec, len(*in))
copy(*out, *in)
}
out.ConfigStore = in.ConfigStore
in.CloudProvider.DeepCopyInto(&out.CloudProvider)
if in.GossipConfig != nil {
in, out := &in.GossipConfig, &out.GossipConfig

View File

@ -51,11 +51,8 @@ type ClusterSpec struct {
Channel string `json:"channel,omitempty"`
// Additional addons that should be installed on the cluster
Addons []AddonSpec `json:"addons,omitempty"`
// ConfigBase is the path where we store configuration for the cluster
// This might be different that the location when the cluster spec itself is stored,
// both because this must be accessible to the cluster,
// and because it might be on a different cloud or storage system (etcd vs S3)
ConfigBase string `json:"configBase,omitempty"`
// ConfigStore configures the stores that nodes use to get their configuration.
ConfigStore ConfigStoreSpec `json:"configStore"`
// CloudProvider configures the cloud provider to use.
CloudProvider CloudProviderSpec `json:"cloudProvider,omitempty"`
// GossipConfig for the cluster assuming the use of gossip DNS
@ -64,10 +61,6 @@ type ClusterSpec struct {
ContainerRuntime string `json:"containerRuntime,omitempty"`
// The version of kubernetes to install (optional, and can be a "spec" like stable)
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
// SecretStore is the VFS path to where secrets are stored
SecretStore string `json:"secretStore,omitempty"`
// KeyStore is the VFS path to where SSL keys and certificates are stored
KeyStore string `json:"keyStore,omitempty"`
// DNSZone is the DNS zone we should use when configuring DNS
// This is because some clouds let us define a managed zone foo.bar, and then have
// kubernetes.dev.foo.bar, without needing to define dev.foo.bar as a hosted zone.
@ -164,6 +157,19 @@ type ClusterSpec struct {
Karpenter *KarpenterConfig `json:"karpenter,omitempty"`
}
// ConfigStoreSpec configures the stores that nodes use to get their configuration.
type ConfigStoreSpec struct {
// Base is the VFS path where we store configuration for the cluster
// This might be different than the location where the cluster spec itself is stored,
// both because this must be accessible to the cluster,
// and because it might be on a different cloud or storage system (etcd vs S3).
Base string `json:"base,omitempty"`
// Keypairs is the VFS path to where certificates and corresponding private keys are stored.
Keypairs string `json:"keypairs,omitempty"`
// Secrets is the VFS path to where secrets are stored.
Secrets string `json:"secrets,omitempty"`
}
// PodIdentityWebhookSpec configures an EKS Pod Identity Webhook.
type PodIdentityWebhookSpec struct {
Enabled bool `json:"enabled,omitempty"`

View File

@ -324,6 +324,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ConfigStoreSpec)(nil), (*kops.ConfigStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec(a.(*ConfigStoreSpec), b.(*kops.ConfigStoreSpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kops.ConfigStoreSpec)(nil), (*ConfigStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec(a.(*kops.ConfigStoreSpec), b.(*ConfigStoreSpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ContainerdConfig)(nil), (*kops.ContainerdConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ContainerdConfig_To_kops_ContainerdConfig(a.(*ContainerdConfig), b.(*kops.ContainerdConfig), scope)
}); err != nil {
@ -2576,7 +2586,9 @@ func autoConvert_v1alpha3_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
} else {
out.Addons = nil
}
out.ConfigBase = in.ConfigBase
if err := Convert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec(&in.ConfigStore, &out.ConfigStore, s); err != nil {
return err
}
if err := Convert_v1alpha3_CloudProviderSpec_To_kops_CloudProviderSpec(&in.CloudProvider, &out.CloudProvider, s); err != nil {
return err
}
@ -2591,8 +2603,6 @@ func autoConvert_v1alpha3_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
}
out.ContainerRuntime = in.ContainerRuntime
out.KubernetesVersion = in.KubernetesVersion
out.SecretStore = in.SecretStore
out.KeyStore = in.KeyStore
out.DNSZone = in.DNSZone
if in.DNSControllerGossipConfig != nil {
in, out := &in.DNSControllerGossipConfig, &out.DNSControllerGossipConfig
@ -2909,7 +2919,9 @@ func autoConvert_kops_ClusterSpec_To_v1alpha3_ClusterSpec(in *kops.ClusterSpec,
} else {
out.Addons = nil
}
out.ConfigBase = in.ConfigBase
if err := Convert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec(&in.ConfigStore, &out.ConfigStore, s); err != nil {
return err
}
if err := Convert_kops_CloudProviderSpec_To_v1alpha3_CloudProviderSpec(&in.CloudProvider, &out.CloudProvider, s); err != nil {
return err
}
@ -2924,8 +2936,6 @@ func autoConvert_kops_ClusterSpec_To_v1alpha3_ClusterSpec(in *kops.ClusterSpec,
}
out.ContainerRuntime = in.ContainerRuntime
out.KubernetesVersion = in.KubernetesVersion
out.SecretStore = in.SecretStore
out.KeyStore = in.KeyStore
out.DNSZone = in.DNSZone
if in.DNSControllerGossipConfig != nil {
in, out := &in.DNSControllerGossipConfig, &out.DNSControllerGossipConfig
@ -3287,6 +3297,30 @@ func Convert_kops_ClusterSubnetSpec_To_v1alpha3_ClusterSubnetSpec(in *kops.Clust
return autoConvert_kops_ClusterSubnetSpec_To_v1alpha3_ClusterSubnetSpec(in, out, s)
}
func autoConvert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec(in *ConfigStoreSpec, out *kops.ConfigStoreSpec, s conversion.Scope) error {
out.Base = in.Base
out.Keypairs = in.Keypairs
out.Secrets = in.Secrets
return nil
}
// Convert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec is an autogenerated conversion function.
func Convert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec(in *ConfigStoreSpec, out *kops.ConfigStoreSpec, s conversion.Scope) error {
return autoConvert_v1alpha3_ConfigStoreSpec_To_kops_ConfigStoreSpec(in, out, s)
}
func autoConvert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec(in *kops.ConfigStoreSpec, out *ConfigStoreSpec, s conversion.Scope) error {
out.Base = in.Base
out.Keypairs = in.Keypairs
out.Secrets = in.Secrets
return nil
}
// Convert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec is an autogenerated conversion function.
func Convert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec(in *kops.ConfigStoreSpec, out *ConfigStoreSpec, s conversion.Scope) error {
return autoConvert_kops_ConfigStoreSpec_To_v1alpha3_ConfigStoreSpec(in, out, s)
}
func autoConvert_v1alpha3_ContainerdConfig_To_kops_ContainerdConfig(in *ContainerdConfig, out *kops.ContainerdConfig, s conversion.Scope) error {
out.Address = in.Address
out.ConfigOverride = in.ConfigOverride

View File

@ -995,6 +995,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = make([]AddonSpec, len(*in))
copy(*out, *in)
}
out.ConfigStore = in.ConfigStore
in.CloudProvider.DeepCopyInto(&out.CloudProvider)
if in.GossipConfig != nil {
in, out := &in.GossipConfig, &out.GossipConfig
@ -1262,6 +1263,22 @@ func (in *ClusterSubnetSpec) DeepCopy() *ClusterSubnetSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigStoreSpec) DeepCopyInto(out *ConfigStoreSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigStoreSpec.
func (in *ConfigStoreSpec) DeepCopy() *ConfigStoreSpec {
if in == nil {
return nil
}
out := new(ConfigStoreSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerdConfig) DeepCopyInto(out *ContainerdConfig) {
*out = *in

View File

@ -1092,6 +1092,7 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = make([]AddonSpec, len(*in))
copy(*out, *in)
}
out.ConfigStore = in.ConfigStore
in.CloudProvider.DeepCopyInto(&out.CloudProvider)
if in.GossipConfig != nil {
in, out := &in.GossipConfig, &out.GossipConfig
@ -1382,6 +1383,22 @@ func (in *ClusterSubnetSpec) DeepCopy() *ClusterSubnetSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigStoreSpec) DeepCopyInto(out *ConfigStoreSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigStoreSpec.
func (in *ConfigStoreSpec) DeepCopy() *ConfigStoreSpec {
if in == nil {
return nil
}
out := new(ConfigStoreSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerdConfig) DeepCopyInto(out *ContainerdConfig) {
*out = *in

View File

@ -91,8 +91,8 @@ func (c *RESTClientset) UpdateCluster(ctx context.Context, cluster *kops.Cluster
// ConfigBaseFor implements the ConfigBaseFor method of Clientset for a kubernetes-API state store
func (c *RESTClientset) ConfigBaseFor(cluster *kops.Cluster) (vfs.Path, error) {
if cluster.Spec.ConfigBase != "" {
return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase)
if cluster.Spec.ConfigStore.Base != "" {
return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
}
// URL for clusters looks like https://<server>/apis/kops/v1alpha2/namespaces/<cluster>/clusters/<cluster>
// We probably want to add a subresource for full resources

View File

@ -70,8 +70,8 @@ func (c *VFSClientset) ListClusters(ctx context.Context, options metav1.ListOpti
// ConfigBaseFor implements the ConfigBaseFor method of simple.Clientset for a VFS-backed state store
func (c *VFSClientset) ConfigBaseFor(cluster *kops.Cluster) (vfs.Path, error) {
if cluster.Spec.ConfigBase != "" {
return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase)
if cluster.Spec.ConfigStore.Base != "" {
return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
}
return c.clusters().configBase(cluster.Name)
}
@ -86,7 +86,7 @@ func (c *VFSClientset) AddonsFor(cluster *kops.Cluster) simple.AddonsClient {
}
func (c *VFSClientset) SecretStore(cluster *kops.Cluster) (fi.SecretStore, error) {
if cluster.Spec.SecretStore == "" {
if cluster.Spec.ConfigStore.Secrets == "" {
configBase, err := registry.ConfigBase(c.VFSContext(), cluster)
if err != nil {
return nil, err
@ -94,7 +94,7 @@ func (c *VFSClientset) SecretStore(cluster *kops.Cluster) (fi.SecretStore, error
basedir := configBase.Join("secrets")
return secrets.NewVFSSecretStore(cluster, basedir), nil
} else {
storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.SecretStore)
storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Secrets)
return secrets.NewVFSSecretStore(cluster, storePath), err
}
}
@ -119,14 +119,14 @@ func (c *VFSClientset) SSHCredentialStore(cluster *kops.Cluster) (fi.SSHCredenti
}
func (c *VFSClientset) pkiPath(cluster *kops.Cluster) (vfs.Path, error) {
if cluster.Spec.KeyStore == "" {
if cluster.Spec.ConfigStore.Keypairs == "" {
configBase, err := registry.ConfigBase(c.VFSContext(), cluster)
if err != nil {
return nil, err
}
return configBase.Join("pki"), nil
} else {
storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.KeyStore)
storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Keypairs)
return storePath, err
}
}
@ -208,7 +208,7 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster)
}
}
secretStore := cluster.Spec.SecretStore
secretStore := cluster.Spec.ConfigStore.Secrets
if secretStore != "" {
path, err := c.VFSContext().BuildVfsPath(secretStore)
if err != nil {
@ -220,7 +220,7 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster)
}
}
keyStore := cluster.Spec.KeyStore
keyStore := cluster.Spec.ConfigStore.Keypairs
if keyStore != "" && keyStore != secretStore {
path, err := c.VFSContext().BuildVfsPath(keyStore)
if err != nil {

View File

@ -31,7 +31,9 @@ func TestSSHCredentialStoreOnConfigBase(t *testing.T) {
configBase := "memfs://some/config/base"
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigBase: configBase,
ConfigStore: kops.ConfigStoreSpec{
Base: configBase,
},
},
}
@ -57,8 +59,10 @@ func TestSSHCredentialStoreOnOwnCFS(t *testing.T) {
keyPath := "memfs://keys/some/config/base/pki"
cluster := &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigBase: configBase,
KeyStore: keyPath,
ConfigStore: kops.ConfigStoreSpec{
Base: configBase,
Keypairs: keyPath,
},
},
}

View File

@ -208,12 +208,12 @@ func (r *ClusterVFS) find(ctx context.Context, clusterName string) (*api.Cluster
}
// TODO: Split this out into real version updates / schema changes
if c.Spec.ConfigBase == "" {
if c.Spec.ConfigStore.Base == "" {
configBase, err := r.configBase(clusterName)
if err != nil {
return nil, fmt.Errorf("error building ConfigBase for cluster: %v", err)
return nil, fmt.Errorf("error building ConfigStore.Base for cluster: %v", err)
}
c.Spec.ConfigBase = configBase.Path()
c.Spec.ConfigStore.Base = configBase.Path()
}
return c, nil

View File

@ -56,7 +56,7 @@ func getTestSetupOS(t *testing.T, ctx context.Context) (*RollingUpdateCluster, *
}
assetBuilder := assets.NewAssetBuilder(vfs.Context, inCluster.Spec.Assets, inCluster.Spec.KubernetesVersion, false)
basePath, _ := vfs.Context.BuildVfsPath(inCluster.Spec.ConfigBase)
basePath, _ := vfs.Context.BuildVfsPath(inCluster.Spec.ConfigStore.Base)
clientset := vfsclientset.NewVFSClientset(vfs.Context, basePath)
cluster, err := cloudup.PopulateClusterSpec(ctx, clientset, inCluster, nil, mockcloud, assetBuilder)
if err != nil {

View File

@ -46,7 +46,7 @@ func (b *EtcdManagerOptionsBuilder) BuildOptions(o interface{}) error {
etcdCluster.Backups = &kops.EtcdBackupSpec{}
}
if etcdCluster.Backups.BackupStore == "" {
base := clusterSpec.ConfigBase
base := clusterSpec.ConfigStore.Base
etcdCluster.Backups.BackupStore = urls.Join(base, "backups", "etcd", etcdCluster.Name)
}

View File

@ -6,6 +6,7 @@ spec:
authorization:
alwaysAllow: {}
cloudProvider: {}
configStore: {}
kubernetesVersion: v1.24.0
networking:
topology:

View File

@ -6,6 +6,7 @@ spec:
authorization:
alwaysAllow: {}
cloudProvider: {}
configStore: {}
kubernetesVersion: v1.26.0
networking:
topology:

View File

@ -6,6 +6,7 @@ spec:
authorization:
alwaysAllow: {}
cloudProvider: {}
configStore: {}
kubeScheduler:
maxPersistentVolumes: 20
kubernetesVersion: v1.24.0

View File

@ -38,7 +38,7 @@ func (b *ConfigBuilder) Build(c *fi.CloudupModelBuilderContext) error {
c.AddTask(&fitasks.ManagedFile{
Name: fi.PtrTo(registry.PathKopsVersionUpdated),
Lifecycle: b.Lifecycle,
Base: fi.PtrTo(b.Cluster.Spec.ConfigBase),
Base: fi.PtrTo(b.Cluster.Spec.ConfigStore.Base),
Location: fi.PtrTo(registry.PathKopsVersionUpdated),
Contents: fi.NewStringResource(kopsbase.Version),
})
@ -50,7 +50,7 @@ func (b *ConfigBuilder) Build(c *fi.CloudupModelBuilderContext) error {
c.AddTask(&fitasks.ManagedFile{
Name: fi.PtrTo(registry.PathClusterCompleted),
Lifecycle: b.Lifecycle,
Base: fi.PtrTo(b.Cluster.Spec.ConfigBase),
Base: fi.PtrTo(b.Cluster.Spec.ConfigStore.Base),
Location: fi.PtrTo(registry.PathClusterCompleted),
Contents: fi.NewBytesResource(versionedYaml),
})

View File

@ -55,7 +55,7 @@ func (b *StorageAclBuilder) Build(c *fi.CloudupModelBuilderContext) error {
return fmt.Errorf("error fetching default ServiceAccount: %w", err)
}
clusterPath := b.Cluster.Spec.ConfigBase
clusterPath := b.Cluster.Spec.ConfigStore.Base
p, err := vfs.Context.BuildVfsPath(clusterPath)
if err != nil {
return fmt.Errorf("cannot parse cluster path %q: %w", clusterPath, err)
@ -179,9 +179,9 @@ func (b *StorageAclBuilder) Build(c *fi.CloudupModelBuilderContext) error {
return err
}
if len(readablePaths) != 0 {
p, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.ConfigBase)
p, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.ConfigStore.Base)
if err != nil {
return fmt.Errorf("cannot parse VFS path %q: %v", b.Cluster.Spec.ConfigBase, err)
return fmt.Errorf("cannot parse VFS path %q: %v", b.Cluster.Spec.ConfigStore.Base, err)
}
gcsPath, ok := p.(*vfs.GSPath)

View File

@ -504,9 +504,9 @@ func (b *PolicyBuilder) AddS3Permissions(p *Policy) (*Policy, error) {
var locations []string
for _, p := range []string{
b.Cluster.Spec.KeyStore,
b.Cluster.Spec.SecretStore,
b.Cluster.Spec.ConfigBase,
b.Cluster.Spec.ConfigStore.Keypairs,
b.Cluster.Spec.ConfigStore.Secrets,
b.Cluster.Spec.ConfigStore.Base,
} {
if p == "" {
continue

View File

@ -174,7 +174,9 @@ func TestPolicyGeneration(t *testing.T) {
b := &PolicyBuilder{
Cluster: &kops.Cluster{
Spec: kops.ClusterSpec{
ConfigBase: "s3://kops-tests/iam-builder-test.k8s.local",
ConfigStore: kops.ConfigStoreSpec{
Base: "s3://kops-tests/iam-builder-test.k8s.local",
},
IAM: &kops.IAMSpec{
AllowContainerRegistry: x.AllowContainerRegistry,
},

View File

@ -69,7 +69,7 @@ func (b *PKIModelBuilder) Build(c *fi.CloudupModelBuilderContext) error {
}
{
mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.SecretStore)
mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.ConfigStore.Secrets)
if err != nil {
return err
}
@ -83,7 +83,7 @@ func (b *PKIModelBuilder) Build(c *fi.CloudupModelBuilderContext) error {
}
{
mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.KeyStore)
mirrorPath, err := vfs.Context.BuildVfsPath(b.Cluster.Spec.ConfigStore.Keypairs)
if err != nil {
return err
}

View File

@ -55,7 +55,9 @@ func BuildMinimalCluster(clusterName string) *kops.Cluster {
c.Spec.Networking.NonMasqueradeCIDR = "100.64.0.0/10"
c.Spec.CloudProvider.AWS = &kops.AWSSpec{}
c.Spec.ConfigBase = "memfs://unittest-bucket/" + clusterName
c.Spec.ConfigStore = kops.ConfigStoreSpec{
Base: "memfs://unittest-bucket/" + clusterName,
}
c.Spec.DNSZone = "test.com"

View File

@ -41,6 +41,7 @@ metadata:
spec:
api: {}
cloudProvider: {}
configStore: {}
kubeControllerManager: {}
kubelet: {}
networking: {}

View File

@ -67,6 +67,7 @@ spec:
iam:
legacy: false
isolateMasters: true
keyStore: memfs://clusters.example.com/keypairs.example.com
kubernetesApiAccess:
- 0.0.0.0/0
kubernetesVersion: v1.21.0
@ -83,6 +84,7 @@ spec:
podCIDR: 100.64.0.0/16
podIdentityWebhook:
replicas: 14
secretStore: memfs://clusters.example.com/secrets.example.com
serviceClusterIPRange: 100.65.0.0/16
sshAccess:
- 0.0.0.0/0

View File

@ -41,7 +41,10 @@ spec:
spotinstProduct: spot-product
warmPool:
enableLifecycleHook: true
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
keypairs: memfs://clusters.example.com/keypairs.example.com
secrets: memfs://clusters.example.com/secrets.example.com
controlPlaneKubelet:
cpuCFSQuota: true
etcdClusters:

View File

@ -35,7 +35,8 @@ spec:
routeTableName: route-table-name
subscriptionID: subs-id
tenantID: tenant-id
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -18,7 +18,8 @@ spec:
channel: stable
cloudProvider:
aws: {}
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -18,7 +18,8 @@ spec:
channel: stable
cloudProvider:
aws: {}
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -16,7 +16,8 @@ spec:
channel: stable
cloudProvider:
do: {}
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -24,7 +24,8 @@ spec:
enabled: true
project: testProject
serviceAccount: gce-sa
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -18,7 +18,8 @@ spec:
channel: stable
cloudProvider:
aws: {}
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -31,7 +31,8 @@ spec:
- test-az-hints
router:
externalNetwork: test-external-network
configBase: memfs://clusters.example.com/minimal.example.com
configStore:
base: memfs://clusters.example.com/minimal.example.com
etcdClusters:
- cpuRequest: 200m
etcdMembers:

View File

@ -266,9 +266,9 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
cluster := c.Cluster
configBase, err := c.Clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase)
configBase, err := c.Clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err)
return fmt.Errorf("error parsing configStore.base %q: %v", cluster.Spec.ConfigStore.Base, err)
}
if !c.AllowKopsDowngrade {
@ -1175,9 +1175,9 @@ type nodeUpConfigBuilder struct {
}
func newNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBuilder, assets map[architectures.Architecture][]*mirrors.MirroredAsset, encryptionConfigSecretHash string) (model.NodeUpConfigBuilder, error) {
configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase)
configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return nil, fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err)
return nil, fmt.Errorf("error parsing configStore.base %q: %v", cluster.Spec.ConfigStore.Base, err)
}
channels := []string{

View File

@ -215,12 +215,14 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
cluster.Spec.KubernetesVersion = opt.KubernetesVersion
}
cluster.Spec.ConfigBase = opt.ConfigBase
cluster.Spec.ConfigStore = api.ConfigStoreSpec{
Base: opt.ConfigBase,
}
configBase, err := clientset.ConfigBaseFor(cluster)
if err != nil {
return nil, fmt.Errorf("error building ConfigBase for cluster: %v", err)
}
cluster.Spec.ConfigBase = configBase.Path()
cluster.Spec.ConfigStore.Base = configBase.Path()
cluster.Spec.Authorization = &api.AuthorizationSpec{}
if strings.EqualFold(opt.Authorization, AuthorizationFlagAlwaysAllow) {
@ -288,11 +290,11 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
allZones.Insert(opt.ControlPlaneZones...)
if opt.CloudProvider == "" {
cloud, err := clouds.GuessCloudForPath(cluster.Spec.ConfigBase)
cloud, err := clouds.GuessCloudForPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return nil, fmt.Errorf("pass in the cloud provider explicitly using --cloud: %w", err)
}
klog.V(2).Infof("Inferred %q cloud provider from state store %q", cloud, cluster.Spec.ConfigBase)
klog.V(2).Infof("Inferred %q cloud provider from state store %q", cloud, cluster.Spec.ConfigStore.Base)
opt.CloudProvider = string(cloud)
}

View File

@ -163,13 +163,13 @@ func (c *populateClusterSpec) run(ctx context.Context, clientset simple.Clientse
}
}
configBase, err := clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase)
configBase, err := clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigStore.Base)
if err != nil {
return fmt.Errorf("error parsing ConfigBase %q: %v", cluster.Spec.ConfigBase, err)
return fmt.Errorf("error parsing ConfigStore.Base %q: %v", cluster.Spec.ConfigStore.Base, err)
}
if !vfs.IsClusterReadable(configBase) {
// We could implement this approach, but it seems better to get all clouds using cluster-readable storage
return fmt.Errorf("ConfigBase path is not cluster readable: %v", cluster.Spec.ConfigBase)
return fmt.Errorf("ConfigStore.Base path is not cluster readable: %v", cluster.Spec.ConfigStore.Base)
}
keyStore, err := clientset.KeyStore(cluster)
@ -177,15 +177,15 @@ func (c *populateClusterSpec) run(ctx context.Context, clientset simple.Clientse
return err
}
if cluster.Spec.KeyStore == "" {
if cluster.Spec.ConfigStore.Keypairs == "" {
hasVFSPath, ok := keyStore.(fi.HasVFSPath)
if !ok {
// We will mirror to ConfigBase
basedir := configBase.Join("pki")
cluster.Spec.KeyStore = basedir.Path()
cluster.Spec.ConfigStore.Keypairs = basedir.Path()
} else if vfs.IsClusterReadable(hasVFSPath.VFSPath()) {
vfsPath := hasVFSPath.VFSPath()
cluster.Spec.KeyStore = vfsPath.Path()
cluster.Spec.ConfigStore.Keypairs = vfsPath.Path()
} else {
// We could implement this approach, but it seems better to get all clouds using cluster-readable storage
return fmt.Errorf("keyStore path is not cluster readable: %v", hasVFSPath.VFSPath())
@ -197,15 +197,15 @@ func (c *populateClusterSpec) run(ctx context.Context, clientset simple.Clientse
return err
}
if cluster.Spec.SecretStore == "" {
if cluster.Spec.ConfigStore.Secrets == "" {
hasVFSPath, ok := secretStore.(fi.HasVFSPath)
if !ok {
// We will mirror to ConfigBase
basedir := configBase.Join("secrets")
cluster.Spec.SecretStore = basedir.Path()
cluster.Spec.ConfigStore.Secrets = basedir.Path()
} else if vfs.IsClusterReadable(hasVFSPath.VFSPath()) {
vfsPath := hasVFSPath.VFSPath()
cluster.Spec.SecretStore = vfsPath.Path()
cluster.Spec.ConfigStore.Secrets = vfsPath.Path()
} else {
// We could implement this approach, but it seems better to get all clouds using cluster-readable storage
return fmt.Errorf("secrets path is not cluster readable: %v", hasVFSPath.VFSPath())

View File

@ -646,8 +646,8 @@ func (tf *TemplateFunctions) KopsControllerConfig() (string, error) {
config := &kopscontrollerconfig.Options{
ClusterName: cluster.Name,
Cloud: string(cluster.Spec.GetCloudProvider()),
ConfigBase: cluster.Spec.ConfigBase,
SecretStore: cluster.Spec.SecretStore,
ConfigBase: cluster.Spec.ConfigStore.Base,
SecretStore: cluster.Spec.ConfigStore.Secrets,
}
if featureflag.CacheNodeidentityInfo.Enabled() {

View File

@ -240,9 +240,9 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
var keyStore fi.KeystoreReader
if nodeConfig != nil {
modelContext.SecretStore = configserver.NewSecretStore(nodeConfig.NodeSecrets)
} else if c.cluster.Spec.SecretStore != "" {
klog.Infof("Building SecretStore at %q", c.cluster.Spec.SecretStore)
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.SecretStore)
} else if c.cluster.Spec.ConfigStore.Secrets != "" {
klog.Infof("Building SecretStore at %q", c.cluster.Spec.ConfigStore.Secrets)
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.ConfigStore.Secrets)
if err != nil {
return fmt.Errorf("error building secret store path: %v", err)
}
@ -255,9 +255,9 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
if nodeConfig != nil {
modelContext.KeyStore = configserver.NewKeyStore()
} else if c.cluster.Spec.KeyStore != "" {
klog.Infof("Building KeyStore at %q", c.cluster.Spec.KeyStore)
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.KeyStore)
} else if c.cluster.Spec.ConfigStore.Keypairs != "" {
klog.Infof("Building KeyStore at %q", c.cluster.Spec.ConfigStore.Keypairs)
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.ConfigStore.Keypairs)
if err != nil {
return fmt.Errorf("error building key store path: %v", err)
}