From 1bef3c62c85b539019336babf417d8f2ac3c2895 Mon Sep 17 00:00:00 2001 From: Jaswanth Veerapaneni Date: Tue, 4 Feb 2025 09:59:49 -0500 Subject: [PATCH] Add bootstrap self managed addons flag to eks controlplane spec --- ...ster.x-k8s.io_awsmanagedcontrolplanes.yaml | 7 ++++ controlplane/eks/api/v1beta1/conversion.go | 2 +- .../api/v1beta1/zz_generated.conversion.go | 1 + .../v1beta2/awsmanagedcontrolplane_types.go | 6 ++++ .../v1beta2/awsmanagedcontrolplane_webhook.go | 3 ++ .../awsmanagedcontrolplane_webhook_test.go | 14 ++++---- pkg/cloud/scope/managedcontrolplane.go | 5 +++ pkg/cloud/services/eks/cluster.go | 5 +++ pkg/cloud/services/eks/cluster_test.go | 20 ++++++----- test/e2e/data/e2e_eks_conf.yaml | 2 ++ ...r-template-eks-control-plane-bare-eks.yaml | 36 +++++++++++++++++++ 11 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 test/e2e/data/eks/cluster-template-eks-control-plane-bare-eks.yaml diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml index 055e5d9879..0a5464ff7b 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml @@ -2194,6 +2194,13 @@ spec: will be the default. type: string type: object + bootstrapSelfManagedAddons: + default: true + description: |- + BootstrapSelfManagedAddons is used to set configuration options for + bare EKS cluster without EKS default networking addons + If you set this value to false when creating a cluster, the default networking add-ons will not be installed + type: boolean controlPlaneEndpoint: description: ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. diff --git a/controlplane/eks/api/v1beta1/conversion.go b/controlplane/eks/api/v1beta1/conversion.go index bb089b4cf7..d0b894067d 100644 --- a/controlplane/eks/api/v1beta1/conversion.go +++ b/controlplane/eks/api/v1beta1/conversion.go @@ -43,7 +43,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.Partition = restored.Spec.Partition dst.Spec.RestrictPrivateSubnets = restored.Spec.RestrictPrivateSubnets dst.Status.Version = restored.Status.Version - + dst.Spec.BootstrapSelfManagedAddons = restored.Spec.BootstrapSelfManagedAddons return nil } diff --git a/controlplane/eks/api/v1beta1/zz_generated.conversion.go b/controlplane/eks/api/v1beta1/zz_generated.conversion.go index 55d9b204b3..d300d0434e 100644 --- a/controlplane/eks/api/v1beta1/zz_generated.conversion.go +++ b/controlplane/eks/api/v1beta1/zz_generated.conversion.go @@ -403,6 +403,7 @@ func autoConvert_v1beta2_AWSManagedControlPlaneSpec_To_v1beta1_AWSManagedControl if err := Convert_v1beta2_VpcCni_To_v1beta1_VpcCni(&in.VpcCni, &out.VpcCni, s); err != nil { return err } + // WARNING: in.BootstrapSelfManagedAddons requires manual conversion: does not exist in peer-type // WARNING: in.RestrictPrivateSubnets requires manual conversion: does not exist in peer-type if err := Convert_v1beta2_KubeProxy_To_v1beta1_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil { return err diff --git a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go index ac386461a9..9106f4d25a 100644 --- a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go +++ b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go @@ -173,6 +173,12 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned // +optional VpcCni VpcCni `json:"vpcCni,omitempty"` + // BootstrapSelfManagedAddons is used to set configuration options for + // bare EKS cluster without EKS default networking addons + // If you set this value to false when creating a cluster, the default networking add-ons will not be installed + // +kubebuilder:default=true + BootstrapSelfManagedAddons bool `json:"bootstrapSelfManagedAddons,omitempty"` + // RestrictPrivateSubnets indicates that the EKS control plane should only use private subnets. // +kubebuilder:default=false RestrictPrivateSubnets bool `json:"restrictPrivateSubnets,omitempty"` diff --git a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go index abda129f92..47025a9ef5 100644 --- a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go +++ b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go @@ -502,4 +502,7 @@ func (r *AWSManagedControlPlane) Default() { infrav1.SetDefaults_Bastion(&r.Spec.Bastion) infrav1.SetDefaults_NetworkSpec(&r.Spec.NetworkSpec) + + // Set default value for BootstrapSelfManagedAddons + r.Spec.BootstrapSelfManagedAddons = true } diff --git a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go index 7441040b8e..6fe1b62c2a 100644 --- a/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go +++ b/controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go @@ -85,21 +85,21 @@ func TestDefaultingWebhook(t *testing.T) { resourceName: "cluster1", resourceNS: "default", expectHash: false, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "less than 100 chars, dot in name", resourceName: "team1.cluster1", resourceNS: "default", expectHash: false, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_team1_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_team1_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "more than 100 chars", resourceName: "abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde", resourceNS: "default", expectHash: true, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "capi_", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "capi_", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "with patch", @@ -107,7 +107,7 @@ func TestDefaultingWebhook(t *testing.T) { resourceNS: "default", expectHash: false, spec: AWSManagedControlPlaneSpec{Version: &vV1_17_1}, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", Version: &vV1_17_1, IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", Version: &vV1_17_1, IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "with allowed ip on bastion", @@ -115,7 +115,7 @@ func TestDefaultingWebhook(t *testing.T) { resourceNS: "default", expectHash: false, spec: AWSManagedControlPlaneSpec{Bastion: infrav1.Bastion{AllowedCIDRBlocks: []string{"100.100.100.100/0"}}}, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: infrav1.Bastion{AllowedCIDRBlocks: []string{"100.100.100.100/0"}}, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: infrav1.Bastion{AllowedCIDRBlocks: []string{"100.100.100.100/0"}}, NetworkSpec: defaultNetworkSpec, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "with CNI on network", @@ -123,14 +123,14 @@ func TestDefaultingWebhook(t *testing.T) { resourceNS: "default", expectHash: false, spec: AWSManagedControlPlaneSpec{NetworkSpec: infrav1.NetworkSpec{CNI: &infrav1.CNISpec{}}}, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: infrav1.NetworkSpec{CNI: &infrav1.CNISpec{}, VPC: defaultVPCSpec}, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: infrav1.NetworkSpec{CNI: &infrav1.CNISpec{}, VPC: defaultVPCSpec}, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, { name: "secondary CIDR", resourceName: "cluster1", resourceNS: "default", expectHash: false, - expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, SecondaryCidrBlock: nil, TokenMethod: &EKSTokenMethodIAMAuthenticator}, + expectSpec: AWSManagedControlPlaneSpec{EKSClusterName: "default_cluster1", IdentityRef: defaultIdentityRef, Bastion: defaultTestBastion, NetworkSpec: defaultNetworkSpec, SecondaryCidrBlock: nil, TokenMethod: &EKSTokenMethodIAMAuthenticator, BootstrapSelfManagedAddons: true}, }, } diff --git a/pkg/cloud/scope/managedcontrolplane.go b/pkg/cloud/scope/managedcontrolplane.go index 14ded92263..5f8b9cd938 100644 --- a/pkg/cloud/scope/managedcontrolplane.go +++ b/pkg/cloud/scope/managedcontrolplane.go @@ -424,6 +424,11 @@ func (s *ManagedControlPlaneScope) DisableVPCCNI() bool { return s.ControlPlane.Spec.VpcCni.Disable } +// BootstrapSelfManagedAddons returns whether the AWS EKS networking addons should be disabled. +func (s *ManagedControlPlaneScope) BootstrapSelfManagedAddons() bool { + return s.ControlPlane.Spec.BootstrapSelfManagedAddons +} + // VpcCni returns a list of environment variables to apply to the `aws-node` DaemonSet. func (s *ManagedControlPlaneScope) VpcCni() ekscontrolplanev1.VpcCni { return s.ControlPlane.Spec.VpcCni diff --git a/pkg/cloud/services/eks/cluster.go b/pkg/cloud/services/eks/cluster.go index 44f6e2eb0a..7dac037d8d 100644 --- a/pkg/cloud/services/eks/cluster.go +++ b/pkg/cloud/services/eks/cluster.go @@ -473,6 +473,11 @@ func (s *Service) createCluster(eksClusterName string) (*eks.Cluster, error) { Tags: tags, KubernetesNetworkConfig: netConfig, } + // Only set BootstrapSelfManagedAddons if it's explicitly set to false in the spec + // Default is true, so we don't need to set it in that case + if !s.scope.BootstrapSelfManagedAddons() { + input.BootstrapSelfManagedAddons = aws.Bool(false) + } var out *eks.CreateClusterOutput if err := wait.WaitForWithRetryable(wait.NewBackoff(), func() (bool, error) { diff --git a/pkg/cloud/services/eks/cluster_test.go b/pkg/cloud/services/eks/cluster_test.go index 7079c62de5..c01c945a50 100644 --- a/pkg/cloud/services/eks/cluster_test.go +++ b/pkg/cloud/services/eks/cluster_test.go @@ -519,10 +519,11 @@ func TestCreateCluster(t *testing.T) { }, ControlPlane: &ekscontrolplanev1.AWSManagedControlPlane{ Spec: ekscontrolplanev1.AWSManagedControlPlaneSpec{ - EKSClusterName: clusterName, - Version: version, - RoleName: tc.role, - NetworkSpec: infrav1.NetworkSpec{Subnets: tc.subnets}, + EKSClusterName: clusterName, + Version: version, + RoleName: tc.role, + NetworkSpec: infrav1.NetworkSpec{Subnets: tc.subnets}, + BootstrapSelfManagedAddons: false, }, }, }) @@ -541,9 +542,10 @@ func TestCreateCluster(t *testing.T) { ResourcesVpcConfig: &eks.VpcConfigRequest{ SubnetIds: subnetIDs, }, - RoleArn: tc.role, - Tags: tc.tags, - Version: version, + RoleArn: tc.role, + Tags: tc.tags, + Version: version, + BootstrapSelfManagedAddons: aws.Bool(false), }).Return(&eks.CreateClusterOutput{}, nil) } s := NewService(scope) @@ -728,7 +730,8 @@ func TestCreateIPv6Cluster(t *testing.T) { }, VPC: vpcSpec, }, - EncryptionConfig: encryptionConfig, + EncryptionConfig: encryptionConfig, + BootstrapSelfManagedAddons: false, }, }, }) @@ -754,6 +757,7 @@ func TestCreateIPv6Cluster(t *testing.T) { Tags: map[string]*string{ "kubernetes.io/cluster/cluster-name": ptr.To[string]("owned"), }, + BootstrapSelfManagedAddons: aws.Bool(false), }).Return(&eks.CreateClusterOutput{}, nil) iamMock.EXPECT().GetRole(&iam.GetRoleInput{ RoleName: aws.String("arn-role"), diff --git a/test/e2e/data/e2e_eks_conf.yaml b/test/e2e/data/e2e_eks_conf.yaml index c3f893afae..156c0f7035 100644 --- a/test/e2e/data/e2e_eks_conf.yaml +++ b/test/e2e/data/e2e_eks_conf.yaml @@ -114,6 +114,8 @@ providers: targetName: "cluster-template-eks-ipv6-cluster.yaml" - sourcePath: "./eks/cluster-template-eks-control-plane-only-legacy.yaml" targetName: "cluster-template-eks-control-plane-only-legacy.yaml" + - sourcePath: "./eks/cluster-template-eks-control-plane-bare-eks.yaml" + targetName: "cluster-template-eks-control-plane-bare-eks.yaml" variables: KUBERNETES_VERSION: "v1.31.0" diff --git a/test/e2e/data/eks/cluster-template-eks-control-plane-bare-eks.yaml b/test/e2e/data/eks/cluster-template-eks-control-plane-bare-eks.yaml new file mode 100644 index 0000000000..b2cd153bb1 --- /dev/null +++ b/test/e2e/data/eks/cluster-template-eks-control-plane-bare-eks.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: cluster.x-k8s.io/v1beta1 +kind: Cluster +metadata: + name: "${CLUSTER_NAME}" +spec: + clusterNetwork: + pods: + cidrBlocks: ["192.168.0.0/16"] + infrastructureRef: + kind: AWSManagedCluster + apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 + name: "${CLUSTER_NAME}" + controlPlaneRef: + kind: AWSManagedControlPlane + apiVersion: controlplane.cluster.x-k8s.io/v1beta2 + name: "${CLUSTER_NAME}-control-plane" +--- +kind: AWSManagedCluster +apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 +metadata: + name: "${CLUSTER_NAME}" +spec: {} +--- +kind: AWSManagedControlPlane +apiVersion: controlplane.cluster.x-k8s.io/v1beta2 +metadata: + name: "${CLUSTER_NAME}-control-plane" +spec: + region: "${AWS_REGION}" + sshKeyName: "${AWS_SSH_KEY_NAME}" + version: "${KUBERNETES_VERSION}" + identityRef: + kind: AWSClusterStaticIdentity + name: e2e-account + bootstrapSelfManagedAddons: false