From 4d0ff5f3846c9604897fd616208f236192012d9b Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Sat, 18 Mar 2023 19:29:09 +0100 Subject: [PATCH] [Compute] Add NewNovaExternalComputeSpec default ctor The dataplane-operator instantiate NovaExternalCompute directly from golang. But wants to rely on defaulted NovaExternalCompute.Spec fields by not filling them. Instantiating the NovaExternalComputeSpec struct directly would result in not defined field to get its golang defaults values instead of the defaults defined in the CRD. The omitempty json tag would only be helpful for those fields where we never want to set the golang default value explicitly as a field value, as that would be ignored. So this patch introduces the NewNovaExternalComputeSpec struct constructor that fills the defaulted fields to its CRD defaults. Unfortunately the CRD defaults are defined in as kubebuilder annotations comments so the default values now duplicated in the implementation. To avoid getting the default values out of sync between the CRD and the NewNovaExternalComputeSpec implementation a test is added that creates the NovaExternalCompute twice with only the required fields provided. First created via unstructured map[string]interface{} construct to leave out the undefined fields from the request. Secondly created via the NewNovaExternalComputeSpec constructor and a normal golang Create API request. Then the two NovaExternalCompute instances are read back from the API and their spec is compared with DeepEqual. --- api/v1beta1/novaexternalcompute_types.go | 18 ++++++++++++ .../novaexternalcompute_controller_test.go | 29 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/api/v1beta1/novaexternalcompute_types.go b/api/v1beta1/novaexternalcompute_types.go index a99b3633a..96f92172e 100644 --- a/api/v1beta1/novaexternalcompute_types.go +++ b/api/v1beta1/novaexternalcompute_types.go @@ -137,3 +137,21 @@ func (c NovaExternalCompute) IsReady() bool { readyCond := c.Status.Conditions.Get(condition.ReadyCondition) return readyCond != nil && readyCond.Status == corev1.ConditionTrue } + +// NewNovaExternalComputeSpec returns a NovaExternalComputeSpec where the fields are defaulted according +// to the CRD definition +func NewNovaExternalComputeSpec(inventoryConfigMapName string, sshKeySecretName string) NovaExternalComputeSpec { + return NovaExternalComputeSpec{ + NovaInstance: "nova", + CellName: "cell1", + CustomServiceConfig: "", + DefaultConfigOverwrite: nil, + InventoryConfigMapName: inventoryConfigMapName, + SSHKeySecretName: sshKeySecretName, + Deploy: true, + NovaComputeContainerImage: "quay.io/tripleozedcentos9/openstack-nova-compute:current-tripleo", + NovaLibvirtContainerImage: "quay.io/tripleozedcentos9/openstack-nova-libvirt:current-tripleo", + AnsibleEEContainerImage: "quay.io/openstack-k8s-operators/openstack-ansibleee-runner:latest", + NetworkAttachments: nil, + } +} diff --git a/test/functional/novaexternalcompute_controller_test.go b/test/functional/novaexternalcompute_controller_test.go index c21f9bb59..648daaee1 100644 --- a/test/functional/novaexternalcompute_controller_test.go +++ b/test/functional/novaexternalcompute_controller_test.go @@ -25,6 +25,7 @@ import ( . "github.com/openstack-k8s-operators/lib-common/modules/test/helpers" corev1 "k8s.io/api/core/v1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" novav1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1" @@ -380,4 +381,32 @@ var _ = Describe("NovaExternalCompute", func() { ) }) }) + When("created as unstructured and created from golang", func() { + It("has the same defaults", func() { + computeNameUnstructured := types.NamespacedName{Namespace: computeName.Namespace, Name: "compute-default-unstructured"} + computeNameGolang := types.NamespacedName{Namespace: computeName.Namespace, Name: "compute-default-golang"} + CreateNovaExternalCompute( + computeNameUnstructured, + map[string]interface{}{ + "inventoryConfigMapName": "foo-inventory-configmap", + "sshKeySecretName": "foo-ssh-key-secret", + }) + computeFromUnstructured := GetNovaExternalCompute(computeNameUnstructured) + DeferCleanup(DeleteInstance, computeFromUnstructured) + + spec := novav1.NewNovaExternalComputeSpec("foo-inventory-configmap", "foo-ssh-key-secret") + err := k8sClient.Create(ctx, &novav1.NovaExternalCompute{ + ObjectMeta: metav1.ObjectMeta{ + Name: computeNameGolang.Name, + Namespace: computeNameGolang.Namespace, + }, + Spec: spec, + }) + Expect(err).ShouldNot(HaveOccurred()) + computeFromGolang := GetNovaExternalCompute(computeNameGolang) + DeferCleanup(DeleteInstance, computeFromGolang) + + Expect(computeFromUnstructured.Spec).To(Equal(computeFromGolang.Spec)) + }) + }) })