From 06dd0f0ec6c96214e4bc984fc3a832e657c3f5c7 Mon Sep 17 00:00:00 2001 From: EmilyL <70486866+dtclxy64@users.noreply.github.com> Date: Fri, 3 Jan 2025 15:29:09 -0500 Subject: [PATCH] Add the registration-auth flag for initializing an EKS cluster as hub. Signed-off-by: Gaurav Jaswal --- go.mod | 2 +- go.sum | 4 +-- pkg/cmd/init/cmd.go | 4 +++ pkg/cmd/init/exec.go | 27 +++++++++++++++++++ pkg/cmd/init/options.go | 3 +++ test/e2e/clusteradm/init_test.go | 27 +++++++++++++++++++ vendor/modules.txt | 2 +- ...ter-management.io_clustermanagers.crd.yaml | 25 +++++++++++++++++ .../api/operator/v1/types_clustermanager.go | 22 +++++++++++++++ .../api/operator/v1/zz_generated.deepcopy.go | 21 +++++++++++++++ .../v1/zz_generated.swagger_doc_generated.go | 14 ++++++++-- 11 files changed, 145 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4bd6133e9..fc6ff5b54 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( k8s.io/klog/v2 v2.130.1 k8s.io/kubectl v0.31.1 k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 - open-cluster-management.io/api v0.15.1-0.20250109024121-1a5e25a78a43 + open-cluster-management.io/api v0.15.1-0.20250116010516-3a595d6a4e40 open-cluster-management.io/cluster-proxy v0.4.0 open-cluster-management.io/managed-serviceaccount v0.6.0 open-cluster-management.io/ocm v0.15.1-0.20250116085531-34275ef1eac8 diff --git a/go.sum b/go.sum index a9d0f0fbd..99c58dc45 100644 --- a/go.sum +++ b/go.sum @@ -557,8 +557,8 @@ k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI= k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -open-cluster-management.io/api v0.15.1-0.20250109024121-1a5e25a78a43 h1:9kgKRQQHMGNM1t+J+OrmF7hgZmND9kRwyRVnHIULzqw= -open-cluster-management.io/api v0.15.1-0.20250109024121-1a5e25a78a43/go.mod h1:9erZEWEn4bEqh0nIX2wA7f/s3KCuFycQdBrPrRzi0QM= +open-cluster-management.io/api v0.15.1-0.20250116010516-3a595d6a4e40 h1:LckTHZ68rcy3hDFu6wa7BVOJ9wbWItJLZXmi0bpMyh8= +open-cluster-management.io/api v0.15.1-0.20250116010516-3a595d6a4e40/go.mod h1:9erZEWEn4bEqh0nIX2wA7f/s3KCuFycQdBrPrRzi0QM= open-cluster-management.io/cluster-proxy v0.4.0 h1:rm0UDaDWe3/P3xLzwqdHtqNksKwSzsic02MkrEe6BnM= open-cluster-management.io/cluster-proxy v0.4.0/go.mod h1:gTvfDHAhGezhdg4BD3ECBn6jbg2Y5PbHhV2ceW5nrB0= open-cluster-management.io/managed-serviceaccount v0.6.0 h1:qIi5T9WQJBuoGqnYGIktXbtqfQoiN2H9XU2P/6lAQiw= diff --git a/pkg/cmd/init/cmd.go b/pkg/cmd/init/cmd.go index cce10e701..c2fddb3fd 100644 --- a/pkg/cmd/init/cmd.go +++ b/pkg/cmd/init/cmd.go @@ -14,6 +14,9 @@ import ( var example = ` # Init the hub %[1]s init + +# Initialize the hub cluster with the type of authentication. Either or both of csr,awsirsa +%[1]s init --registration-auth awsirsa --registration-auth csr ` // NewCmd ... @@ -78,6 +81,7 @@ func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, stream _ = clusterManagerSet.SetAnnotation("singleton-name", "singletonSet", []string{}) o.Helm.AddFlags(singletonSet) cmd.Flags().AddFlagSet(singletonSet) + cmd.Flags().StringArrayVar(&o.registrationAuth, "registration-auth", []string{}, "The type of authentication to use for registering and authenticating with hub, this flag can be repeated to specify multiple authentication types.") return cmd } diff --git a/pkg/cmd/init/exec.go b/pkg/cmd/init/exec.go index 1040c47f4..082224561 100644 --- a/pkg/cmd/init/exec.go +++ b/pkg/cmd/init/exec.go @@ -15,6 +15,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/retry" "k8s.io/klog/v2" + "k8s.io/utils/strings/slices" ocmfeature "open-cluster-management.io/api/feature" operatorv1 "open-cluster-management.io/api/operator/v1" "open-cluster-management.io/clusteradm/pkg/cmd/init/preflight" @@ -70,10 +71,15 @@ func (o *Options) complete(cmd *cobra.Command, args []string) (err error) { }, Tag: bundleVersion.OCM, } + registrationDrivers, err := getRegistrationDrivers(o) + if err != nil { + return err + } o.clusterManagerChartConfig.ClusterManager = chart.ClusterManagerConfig{ RegistrationConfiguration: operatorv1.RegistrationHubConfiguration{ FeatureGates: genericclioptionsclusteradm.ConvertToFeatureGateAPI( genericclioptionsclusteradm.HubMutableFeatureGate, ocmfeature.DefaultHubRegistrationFeatureGates), + RegistrationDrivers: registrationDrivers, }, WorkConfiguration: operatorv1.WorkConfiguration{ FeatureGates: genericclioptionsclusteradm.ConvertToFeatureGateAPI( @@ -353,3 +359,24 @@ func (o *Options) deploySingletonControlplane(kubeClient kubernetes.Interface) e } return nil } + +func getRegistrationDrivers(o *Options) ([]operatorv1.RegistrationDriverHub, error) { + registrationDrivers := []operatorv1.RegistrationDriverHub{} + if slices.Contains(o.registrationAuth, "csr") { + registrationDrivers = append(registrationDrivers, operatorv1.RegistrationDriverHub{AuthType: "csr"}) + } + if slices.Contains(o.registrationAuth, "awsirsa") { + rawConfig, err := o.ClusteradmFlags.KubectlFactory.ToRawKubeConfigLoader().RawConfig() + if err != nil { + klog.Errorf("unable to load hub cluster kubeconfig: %v", err) + return nil, err + } + hubClusterArn := rawConfig.Contexts[rawConfig.CurrentContext].Cluster + if hubClusterArn == "" { + klog.Errorf("hubClusterArn has empty value in kubeconfig") + return nil, fmt.Errorf("unable to retrieve hubClusterArn from kubeconfig") + } + registrationDrivers = append(registrationDrivers, operatorv1.RegistrationDriverHub{AuthType: "awsirsa", HubClusterArn: hubClusterArn}) + } + return registrationDrivers, nil +} diff --git a/pkg/cmd/init/options.go b/pkg/cmd/init/options.go index 6a98770fe..63512ea40 100644 --- a/pkg/cmd/init/options.go +++ b/pkg/cmd/init/options.go @@ -50,6 +50,9 @@ type Options struct { output string Streams genericiooptions.IOStreams + + // The type of authentication to use for initializing the hub cluster + registrationAuth []string } func newOptions(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, streams genericiooptions.IOStreams) *Options { diff --git a/test/e2e/clusteradm/init_test.go b/test/e2e/clusteradm/init_test.go index a18907077..6c77ef5a9 100644 --- a/test/e2e/clusteradm/init_test.go +++ b/test/e2e/clusteradm/init_test.go @@ -34,6 +34,33 @@ var _ = ginkgo.Describe("test clusteradm with bootstrap token in singleton mode" gomega.Expect(err).NotTo(gomega.HaveOccurred()) gomega.Expect(len(cm.Spec.RegistrationConfiguration.FeatureGates)).Should(gomega.Equal(1)) + err = e2e.Clusteradm().Init( + "--use-bootstrap-token", + "--context", e2e.Cluster().Hub().Context(), + "--bundle-version=latest", + "--registration-auth awsirsa", + ) + gomega.Expect(err).NotTo(gomega.HaveOccurred(), "clusteradm init error") + + cm, err = operatorClient.OperatorV1().ClusterManagers().Get(context.TODO(), "cluster-manager", metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + // Ensure that when only awsirsa is passed as registration-auth only awsirsa driver is available + gomega.Expect(len(cm.Spec.RegistrationConfiguration.RegistrationDrivers)).Should(gomega.Equal(1)) + + err = e2e.Clusteradm().Init( + "--use-bootstrap-token", + "--context", e2e.Cluster().Hub().Context(), + "--bundle-version=latest", + "--registration-auth awsirsa", + "--registration-auth csr", + ) + gomega.Expect(err).NotTo(gomega.HaveOccurred(), "clusteradm init error") + + cm, err = operatorClient.OperatorV1().ClusterManagers().Get(context.TODO(), "cluster-manager", metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + // Ensure that awsirsa and csr is passed as registration-auth both the values are set. + gomega.Expect(len(cm.Spec.RegistrationConfiguration.RegistrationDrivers)).Should(gomega.Equal(2)) + err = e2e.Clusteradm().Init( "--use-bootstrap-token", "--context", e2e.Cluster().Hub().Context(), diff --git a/vendor/modules.txt b/vendor/modules.txt index 642687d12..f97d3fdb0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1239,7 +1239,7 @@ k8s.io/utils/pointer k8s.io/utils/ptr k8s.io/utils/strings/slices k8s.io/utils/trace -# open-cluster-management.io/api v0.15.1-0.20250109024121-1a5e25a78a43 +# open-cluster-management.io/api v0.15.1-0.20250116010516-3a595d6a4e40 ## explicit; go 1.22.0 open-cluster-management.io/api/addon/v1alpha1 open-cluster-management.io/api/client/addon/clientset/versioned diff --git a/vendor/open-cluster-management.io/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml b/vendor/open-cluster-management.io/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml index 8e92beeb7..c4e3864fa 100644 --- a/vendor/open-cluster-management.io/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml +++ b/vendor/open-cluster-management.io/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml @@ -255,6 +255,31 @@ spec: - feature type: object type: array + registrationDrivers: + description: |- + RegistrationDrivers represent the list of hub registration drivers that contain information used by hub to initialize the hub cluster + A RegistrationDriverHub contains details of authentication type and the hub cluster ARN + items: + properties: + authType: + default: csr + description: Type of the authentication used by hub to initialize + the Hub cluster. Possible values are csr and awsirsa. + enum: + - csr + - awsirsa + type: string + hubClusterArn: + description: |- + This represents the hub cluster ARN + Example - arn:eks:us-west-2:12345678910:cluster/hub-cluster1 + pattern: ^arn:aws:eks:([a-zA-Z0-9-]+):(\d{12}):cluster/([a-zA-Z0-9-]+)$ + type: string + type: object + type: array + x-kubernetes-list-map-keys: + - authType + x-kubernetes-list-type: map type: object registrationImagePullSpec: default: quay.io/open-cluster-management/registration diff --git a/vendor/open-cluster-management.io/api/operator/v1/types_clustermanager.go b/vendor/open-cluster-management.io/api/operator/v1/types_clustermanager.go index 373f87f10..d9d058e69 100644 --- a/vendor/open-cluster-management.io/api/operator/v1/types_clustermanager.go +++ b/vendor/open-cluster-management.io/api/operator/v1/types_clustermanager.go @@ -108,6 +108,28 @@ type RegistrationHubConfiguration struct { // he can set featuregate/Foo=false before upgrading. Let's say the cluster-admin wants featuregate/Foo=false. // +optional FeatureGates []FeatureGate `json:"featureGates,omitempty"` + + // RegistrationDrivers represent the list of hub registration drivers that contain information used by hub to initialize the hub cluster + // A RegistrationDriverHub contains details of authentication type and the hub cluster ARN + // +optional + // +listType=map + // +listMapKey=authType + RegistrationDrivers []RegistrationDriverHub `json:"registrationDrivers,omitempty"` +} + +type RegistrationDriverHub struct { + + // Type of the authentication used by hub to initialize the Hub cluster. Possible values are csr and awsirsa. + // +required + // +kubebuilder:default:=csr + // +kubebuilder:validation:Enum=csr;awsirsa + AuthType string `json:"authType,omitempty"` + + // This represents the hub cluster ARN + // Example - arn:eks:us-west-2:12345678910:cluster/hub-cluster1 + // +optional + // +kubebuilder:validation:Pattern=`^arn:aws:eks:([a-zA-Z0-9-]+):(\d{12}):cluster/([a-zA-Z0-9-]+)$` + HubClusterArn string `json:"hubClusterArn,omitempty"` } type WorkConfiguration struct { diff --git a/vendor/open-cluster-management.io/api/operator/v1/zz_generated.deepcopy.go b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.deepcopy.go index 64a618ba5..96eef484b 100644 --- a/vendor/open-cluster-management.io/api/operator/v1/zz_generated.deepcopy.go +++ b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.deepcopy.go @@ -557,6 +557,22 @@ func (in *RegistrationDriver) DeepCopy() *RegistrationDriver { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistrationDriverHub) DeepCopyInto(out *RegistrationDriverHub) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrationDriverHub. +func (in *RegistrationDriverHub) DeepCopy() *RegistrationDriverHub { + if in == nil { + return nil + } + out := new(RegistrationDriverHub) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RegistrationHubConfiguration) DeepCopyInto(out *RegistrationHubConfiguration) { *out = *in @@ -570,6 +586,11 @@ func (in *RegistrationHubConfiguration) DeepCopyInto(out *RegistrationHubConfigu *out = make([]FeatureGate, len(*in)) copy(*out, *in) } + if in.RegistrationDrivers != nil { + in, out := &in.RegistrationDrivers, &out.RegistrationDrivers + *out = make([]RegistrationDriverHub, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/open-cluster-management.io/api/operator/v1/zz_generated.swagger_doc_generated.go b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.swagger_doc_generated.go index 5d63b9197..7342a4106 100644 --- a/vendor/open-cluster-management.io/api/operator/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.swagger_doc_generated.go @@ -122,9 +122,19 @@ func (NodePlacement) SwaggerDoc() map[string]string { return map_NodePlacement } +var map_RegistrationDriverHub = map[string]string{ + "authType": "Type of the authentication used by hub to initialize the Hub cluster. Possible values are csr and awsirsa.", + "hubClusterArn": "This represents the hub cluster ARN Example - arn:eks:us-west-2:12345678910:cluster/hub-cluster1", +} + +func (RegistrationDriverHub) SwaggerDoc() map[string]string { + return map_RegistrationDriverHub +} + var map_RegistrationHubConfiguration = map[string]string{ - "autoApproveUsers": "AutoApproveUser represents a list of users that can auto approve CSR and accept client. If the credential of the bootstrap-hub-kubeconfig matches to the users, the cluster created by the bootstrap-hub-kubeconfig will be auto-registered into the hub cluster. This takes effect only when ManagedClusterAutoApproval feature gate is enabled.", - "featureGates": "FeatureGates represents the list of feature gates for registration If it is set empty, default feature gates will be used. If it is set, featuregate/Foo is an example of one item in FeatureGates:\n 1. If featuregate/Foo does not exist, registration-operator will discard it\n 2. If featuregate/Foo exists and is false by default. It is now possible to set featuregate/Foo=[false|true]\n 3. If featuregate/Foo exists and is true by default. If a cluster-admin upgrading from 1 to 2 wants to continue having featuregate/Foo=false,\n \the can set featuregate/Foo=false before upgrading. Let's say the cluster-admin wants featuregate/Foo=false.", + "autoApproveUsers": "AutoApproveUser represents a list of users that can auto approve CSR and accept client. If the credential of the bootstrap-hub-kubeconfig matches to the users, the cluster created by the bootstrap-hub-kubeconfig will be auto-registered into the hub cluster. This takes effect only when ManagedClusterAutoApproval feature gate is enabled.", + "featureGates": "FeatureGates represents the list of feature gates for registration If it is set empty, default feature gates will be used. If it is set, featuregate/Foo is an example of one item in FeatureGates:\n 1. If featuregate/Foo does not exist, registration-operator will discard it\n 2. If featuregate/Foo exists and is false by default. It is now possible to set featuregate/Foo=[false|true]\n 3. If featuregate/Foo exists and is true by default. If a cluster-admin upgrading from 1 to 2 wants to continue having featuregate/Foo=false,\n \the can set featuregate/Foo=false before upgrading. Let's say the cluster-admin wants featuregate/Foo=false.", + "registrationDrivers": "RegistrationDrivers represent the list of hub registration drivers that contain information used by hub to initialize the hub cluster A RegistrationDriverHub contains details of authentication type and the hub cluster ARN", } func (RegistrationHubConfiguration) SwaggerDoc() map[string]string {