From a154231c6b72bfdae1a7b95994cfd01703815bea Mon Sep 17 00:00:00 2001 From: Angie Wang Date: Thu, 26 Sep 2024 14:37:29 -0400 Subject: [PATCH] Replace clusterTemplateRef field with templateName and templateVersion --- api/v1alpha1/clusterrequest_types.go | 11 ++++- ...ims.oran.openshift.io_clusterrequests.yaml | 15 ++++-- .../oran-o2ims.clusterserviceversion.yaml | 23 ++++++--- ...ims.oran.openshift.io_clusterrequests.yaml | 15 ++++-- .../oran-o2ims.clusterserviceversion.yaml | 18 +++++-- config/samples/v1alpha1_clusterrequest.yaml | 3 +- config/samples/v1alpha1_clustertemplate.yaml | 2 +- .../controllers/clusterrequest_controller.go | 24 ++++++--- .../clusterrequest_controller_test.go | 49 ++++++++++++------- 9 files changed, 116 insertions(+), 44 deletions(-) diff --git a/api/v1alpha1/clusterrequest_types.go b/api/v1alpha1/clusterrequest_types.go index 469b9230..f2b0d67b 100644 --- a/api/v1alpha1/clusterrequest_types.go +++ b/api/v1alpha1/clusterrequest_types.go @@ -33,8 +33,15 @@ type ClusterRequestSpec struct { //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Location Spec",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} hwv1alpha1.LocationSpec `json:",inline"` - //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Cluster Template Reference",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} - ClusterTemplateRef string `json:"clusterTemplateRef"` + // TemplateName defines the base name of the referenced ClusterTemplate. + // The full name of the ClusterTemplate is constructed as . + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Template Name",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} + TemplateName string `json:"templateName"` + + // TemplateVersion defines the version of the referenced ClusterTemplate. + // The full name of the ClusterTemplate is constructed as . + //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Template Version",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} + TemplateVersion string `json:"templateVersion"` //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Cluster Template Input",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} ClusterTemplateInput ClusterTemplateInput `json:"clusterTemplateInput"` diff --git a/bundle/manifests/o2ims.oran.openshift.io_clusterrequests.yaml b/bundle/manifests/o2ims.oran.openshift.io_clusterrequests.yaml index 4e7cfa81..11f17e0c 100644 --- a/bundle/manifests/o2ims.oran.openshift.io_clusterrequests.yaml +++ b/bundle/manifests/o2ims.oran.openshift.io_clusterrequests.yaml @@ -61,14 +61,22 @@ spec: - clusterInstanceInput - policyTemplateInput type: object - clusterTemplateRef: - type: string location: description: Location type: string site: description: Site type: string + templateName: + description: |- + TemplateName defines the base name of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + type: string + templateVersion: + description: |- + TemplateVersion defines the version of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + type: string timeout: description: |- Timeout contains timeout values for hardware provisioning, cluster provisioning and @@ -92,8 +100,9 @@ spec: type: object required: - clusterTemplateInput - - clusterTemplateRef - site + - templateName + - templateVersion type: object status: description: ClusterRequestStatus defines the observed state of ClusterRequest diff --git a/bundle/manifests/oran-o2ims.clusterserviceversion.yaml b/bundle/manifests/oran-o2ims.clusterserviceversion.yaml index 596b8c93..dc820736 100644 --- a/bundle/manifests/oran-o2ims.clusterserviceversion.yaml +++ b/bundle/manifests/oran-o2ims.clusterserviceversion.yaml @@ -190,8 +190,9 @@ metadata: "sriov-network-vlan-2": "111" } }, - "clusterTemplateRef": "clustertemplate-sample", "site": "local", + "templateName": "clustertemplate-sample", + "templateVersion": "v1.0.0", "timeout": { "clusterProvisioning": 80, "configuration": 40, @@ -210,7 +211,7 @@ metadata: "app.kubernetes.io/name": "clustertemplate", "app.kubernetes.io/part-of": "oran-o2ims" }, - "name": "clustertemplate-sample" + "name": "clustertemplate-sample.v1.0.0" }, "spec": { "inputDataSchema": { @@ -515,10 +516,6 @@ spec: path: clusterTemplateInput x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Cluster Template Reference - path: clusterTemplateRef - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:text - description: Location displayName: Location path: location @@ -529,6 +526,20 @@ spec: path: site x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: |- + TemplateName defines the base name of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + displayName: Template Name + path: templateName + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: |- + TemplateVersion defines the version of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + displayName: Template Version + path: templateVersion + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text - displayName: Timeout path: timeout x-descriptors: diff --git a/config/crd/bases/o2ims.oran.openshift.io_clusterrequests.yaml b/config/crd/bases/o2ims.oran.openshift.io_clusterrequests.yaml index 05905946..a7f908fb 100644 --- a/config/crd/bases/o2ims.oran.openshift.io_clusterrequests.yaml +++ b/config/crd/bases/o2ims.oran.openshift.io_clusterrequests.yaml @@ -61,14 +61,22 @@ spec: - clusterInstanceInput - policyTemplateInput type: object - clusterTemplateRef: - type: string location: description: Location type: string site: description: Site type: string + templateName: + description: |- + TemplateName defines the base name of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + type: string + templateVersion: + description: |- + TemplateVersion defines the version of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + type: string timeout: description: |- Timeout contains timeout values for hardware provisioning, cluster provisioning and @@ -92,8 +100,9 @@ spec: type: object required: - clusterTemplateInput - - clusterTemplateRef - site + - templateName + - templateVersion type: object status: description: ClusterRequestStatus defines the observed state of ClusterRequest diff --git a/config/manifests/bases/oran-o2ims.clusterserviceversion.yaml b/config/manifests/bases/oran-o2ims.clusterserviceversion.yaml index 85aa2641..e59867bf 100644 --- a/config/manifests/bases/oran-o2ims.clusterserviceversion.yaml +++ b/config/manifests/bases/oran-o2ims.clusterserviceversion.yaml @@ -125,10 +125,6 @@ spec: path: clusterTemplateInput x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Cluster Template Reference - path: clusterTemplateRef - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:text - description: Location displayName: Location path: location @@ -139,6 +135,20 @@ spec: path: site x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: |- + TemplateName defines the base name of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + displayName: Template Name + path: templateName + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: |- + TemplateVersion defines the version of the referenced ClusterTemplate. + The full name of the ClusterTemplate is constructed as . + displayName: Template Version + path: templateVersion + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text - displayName: Timeout path: timeout x-descriptors: diff --git a/config/samples/v1alpha1_clusterrequest.yaml b/config/samples/v1alpha1_clusterrequest.yaml index e35d5c52..86952150 100644 --- a/config/samples/v1alpha1_clusterrequest.yaml +++ b/config/samples/v1alpha1_clusterrequest.yaml @@ -14,7 +14,8 @@ spec: clusterProvisioning: 80 configuration: 40 hardwareProvisioning: 60 - clusterTemplateRef: clustertemplate-sample + templateName: clustertemplate-sample + templateVersion: v1.0.0 clusterTemplateInput: policyTemplateInput: sriov-network-vlan-1: "114" diff --git a/config/samples/v1alpha1_clustertemplate.yaml b/config/samples/v1alpha1_clustertemplate.yaml index 8dd962bb..816a28d3 100644 --- a/config/samples/v1alpha1_clustertemplate.yaml +++ b/config/samples/v1alpha1_clustertemplate.yaml @@ -7,7 +7,7 @@ metadata: app.kubernetes.io/part-of: oran-o2ims app.kubernetes.io/managed-by: kustomize app.kubernetes.io/created-by: oran-o2ims - name: clustertemplate-sample + name: clustertemplate-sample.v1.0.0 spec: templates: clusterInstanceDefaults: clusterinstance-defaults-v1 diff --git a/internal/controllers/clusterrequest_controller.go b/internal/controllers/clusterrequest_controller.go index b4b51e7c..9eaf5c7c 100644 --- a/internal/controllers/clusterrequest_controller.go +++ b/internal/controllers/clusterrequest_controller.go @@ -88,6 +88,10 @@ const ( ztpDoneLabel = "ztp-done" ) +func getClusterTemplateRefName(name, version string) string { + return fmt.Sprintf("%s.%s", name, version) +} + //+kubebuilder:rbac:groups=o2ims.oran.openshift.io,resources=clusterrequests,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=o2ims.oran.openshift.io,resources=clusterrequests/status,verbs=get;update;patch //+kubebuilder:rbac:groups=o2ims.oran.openshift.io,resources=clusterrequests/finalizers,verbs=update @@ -1222,6 +1226,8 @@ func (t *clusterRequestReconcilerTask) createExtraManifestsConfigMap( func (t *clusterRequestReconcilerTask) createPullSecret( ctx context.Context, clusterInstance *siteconfig.ClusterInstance) error { + clusterTemplateRefName := getClusterTemplateRefName( + t.object.Spec.TemplateName, t.object.Spec.TemplateVersion) // If we got to this point, we can assume that all the keys exist, including // clusterName @@ -1234,13 +1240,13 @@ func (t *clusterRequestReconcilerTask) createPullSecret( if err != nil { return fmt.Errorf( "failed to check if pull secret %s exists in namespace %s: %w", - t.object.Spec.ClusterTemplateRef, t.object.Spec.ClusterTemplateRef, err, + pullSecretName, clusterTemplateRefName, err, ) } if !pullSecretExistsInTemplateNamespace { return utils.NewInputError( "pull secret %s expected to exist in the %s namespace, but it is missing", - pullSecretName, t.object.Spec.ClusterTemplateRef) + pullSecretName, clusterTemplateRefName) } newClusterInstancePullSecret := &corev1.Secret{ @@ -1473,8 +1479,10 @@ func (t *clusterRequestReconcilerTask) getCrClusterTemplateRef(ctx context.Conte // Check the clusterTemplateRef references an existing template in the same namespace // as the current clusterRequest. clusterTemplateRef := &oranv1alpha1.ClusterTemplate{} + clusterTemplateRefName := getClusterTemplateRefName( + t.object.Spec.TemplateName, t.object.Spec.TemplateVersion) clusterTemplateRefExists, err := utils.DoesK8SResourceExist( - ctx, t.client, t.object.Spec.ClusterTemplateRef, t.object.Namespace, clusterTemplateRef) + ctx, t.client, clusterTemplateRefName, t.object.Namespace, clusterTemplateRef) // If there was an error in trying to get the ClusterTemplate, return it. if err != nil { @@ -1486,7 +1494,7 @@ func (t *clusterRequestReconcilerTask) getCrClusterTemplateRef(ctx context.Conte return nil, utils.NewInputError( fmt.Sprintf( "the referenced ClusterTemplate (%s) does not exist in the %s namespace", - t.object.Spec.ClusterTemplateRef, t.object.Namespace)) + clusterTemplateRefName, t.object.Namespace)) } return clusterTemplateRef, nil } @@ -1506,11 +1514,13 @@ func (t *clusterRequestReconcilerTask) validateClusterTemplateInputMatchesSchema } // Check that the clusterTemplateInput matches the inputDataSchema from the ClusterTemplate. + clusterTemplateRefName := getClusterTemplateRefName( + t.object.Spec.TemplateName, t.object.Spec.TemplateVersion) err = utils.ValidateJsonAgainstJsonSchema( schemaMap, clusterTemplateInput) if err != nil { return fmt.Errorf("the provided clusterTemplateInput for %s does not "+ - "match the schema from the ClusterTemplate (%s): %w", dataType, t.object.Spec.ClusterTemplateRef, err) + "match the schema from the ClusterTemplate (%s): %w", dataType, clusterTemplateRefName, err) } return nil @@ -2030,7 +2040,9 @@ func (r *ClusterRequestReconciler) findClusterTemplateForClusterRequest( // Create reconciling requests only for the clusterRequests that are using the // current clusterTemplate. for _, clusterRequest := range clusterRequests.Items { - if clusterRequest.Spec.ClusterTemplateRef == newClusterTemplate.GetName() { + clusterTemplateRefName := getClusterTemplateRefName( + clusterRequest.Spec.TemplateName, clusterRequest.Spec.TemplateVersion) + if clusterTemplateRefName == newClusterTemplate.GetName() { r.Logger.Info( "[findClusterRequestsForClusterTemplate] Add new reconcile request for ClusterRequest", "name", clusterRequest.Name) diff --git a/internal/controllers/clusterrequest_controller_test.go b/internal/controllers/clusterrequest_controller_test.go index 2fc66610..cd8c8642 100644 --- a/internal/controllers/clusterrequest_controller_test.go +++ b/internal/controllers/clusterrequest_controller_test.go @@ -466,7 +466,8 @@ var _ = Describe("ClusterRequestReconcile", func() { req reconcile.Request cr *oranv1alpha1.ClusterRequest ct *oranv1alpha1.ClusterTemplate - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" ciDefaultsCm = "clusterinstance-defaults-v1" ptDefaultsCm = "policytemplate-defaults-v1" @@ -546,7 +547,7 @@ var _ = Describe("ClusterRequestReconcile", func() { // Define the cluster template. ct = &oranv1alpha1.ClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: ctName, + Name: getClusterTemplateRefName(tName, tVersion), Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterTemplateSpec{ @@ -583,7 +584,8 @@ var _ = Describe("ClusterRequestReconcile", func() { Finalizers: []string{clusterRequestFinalizer}, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, ClusterTemplateInput: oranv1alpha1.ClusterTemplateInput{ ClusterInstanceInput: runtime.RawExtension{ Raw: []byte(testClusterTemplateInput), @@ -1168,7 +1170,8 @@ var _ = Describe("getCrClusterTemplateRef", func() { c client.Client reconciler *ClusterRequestReconciler task *clusterRequestReconcilerTask - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" ciDefaultsCm = "clusterinstance-defaults-v1" ptDefaultsCm = "policytemplate-defaults-v1" @@ -1185,7 +1188,8 @@ var _ = Describe("getCrClusterTemplateRef", func() { Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, }, } @@ -1225,12 +1229,13 @@ var _ = Describe("getCrClusterTemplateRef", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring( fmt.Sprintf("the referenced ClusterTemplate (%s) does not exist in the %s namespace", - ctName, ctNamespace))) + getClusterTemplateRefName(tName, tVersion), ctNamespace))) Expect(retCt).To(Equal((*oranv1alpha1.ClusterTemplate)(nil))) }) It("returns the referred ClusterTemplate if it exists", func() { // Define the cluster template. + ctName := getClusterTemplateRefName(tName, tVersion) ct := &oranv1alpha1.ClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ Name: ctName, @@ -1264,7 +1269,8 @@ var _ = Describe("createPolicyTemplateConfigMap", func() { c client.Client reconciler *ClusterRequestReconciler task *clusterRequestReconcilerTask - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" crName = "cluster-1" ) @@ -1278,7 +1284,8 @@ var _ = Describe("createPolicyTemplateConfigMap", func() { Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, }, } @@ -1345,7 +1352,8 @@ var _ = Describe("renderHardwareTemplate", func() { task *clusterRequestReconcilerTask clusterInstance *siteconfig.ClusterInstance ct *oranv1alpha1.ClusterTemplate - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" hwTemplateCm = "hwTemplate-v1" crName = "cluster-1" @@ -1399,14 +1407,15 @@ var _ = Describe("renderHardwareTemplate", func() { Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, }, } // Define the cluster template. ct = &oranv1alpha1.ClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: ctName, + Name: getClusterTemplateRefName(tName, tVersion), Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterTemplateSpec{ @@ -1851,7 +1860,8 @@ var _ = Describe("policyManagement", func() { CRReconciler *ClusterRequestReconciler CRTask *clusterRequestReconcilerTask CTReconciler *ClusterTemplateReconciler - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" ciDefaultsCm = "clusterinstance-defaults-v1" ptDefaultsCm = "policytemplate-defaults-v1" @@ -1871,7 +1881,7 @@ var _ = Describe("policyManagement", func() { // Cluster Template. &oranv1alpha1.ClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: ctName, + Name: getClusterTemplateRefName(tName, tVersion), Namespace: ctNamespace, }, Spec: oranv1alpha1.ClusterTemplateSpec{ @@ -1963,7 +1973,8 @@ defaultHugepagesSize: "1G"`, Finalizers: []string{clusterRequestFinalizer}, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, ClusterTemplateInput: oranv1alpha1.ClusterTemplateInput{ ClusterInstanceInput: runtime.RawExtension{ Raw: []byte(testClusterTemplateInput), @@ -2006,7 +2017,7 @@ defaultHugepagesSize: "1G"`, req := reconcile.Request{ NamespacedName: types.NamespacedName{ - Name: ctName, + Name: getClusterTemplateRefName(tName, tVersion), Namespace: ctNamespace, }, } @@ -3478,7 +3489,8 @@ var _ = Describe("hasPolicyConfigurationTimedOut", func() { CRReconciler *ClusterRequestReconciler CRTask *clusterRequestReconcilerTask CTReconciler *ClusterTemplateReconciler - ctName = "clustertemplate-a-v1" + tName = "clustertemplate-a" + tVersion = "v1.0.0" ctNamespace = "clustertemplate-a-v4-16" ) @@ -3499,7 +3511,8 @@ var _ = Describe("hasPolicyConfigurationTimedOut", func() { Finalizers: []string{clusterRequestFinalizer}, }, Spec: oranv1alpha1.ClusterRequestSpec{ - ClusterTemplateRef: ctName, + TemplateName: tName, + TemplateVersion: tVersion, ClusterTemplateInput: oranv1alpha1.ClusterTemplateInput{ ClusterInstanceInput: runtime.RawExtension{ Raw: []byte(testClusterTemplateInput), @@ -3527,7 +3540,7 @@ var _ = Describe("hasPolicyConfigurationTimedOut", func() { req := reconcile.Request{ NamespacedName: types.NamespacedName{ - Name: ctName, + Name: getClusterTemplateRefName(tName, tVersion), Namespace: ctNamespace, }, }