diff --git a/Makefile b/Makefile index 505ad5f..a33e74a 100644 --- a/Makefile +++ b/Makefile @@ -449,6 +449,9 @@ SKIP_CERT ?=false .PHONY: run-with-webhook run-with-webhook: export METRICS_PORT?=33080 run-with-webhook: export HEALTH_PORT?=33081 +run-with-webhook: export WATCHER_API_IMAGE_URL_DEFAULT=quay.io/podified-main-centos9/openstack-watcher-api:current-podified +run-with-webhook: export WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT=quay.io/podified-main-centos9/openstack-watcher-decision-engine:current-podified +run-with-webhook: export WATCHER_APPLIER_IMAGE_URL_DEFAULT=quay.io/podified-main-centos9/openstack-watcher-applier:current-podified run-with-webhook: manifests generate fmt vet ## Run a controller from your host. /bin/bash hack/clean_local_webhook.sh /bin/bash hack/run_with_local_webhook.sh diff --git a/api/bases/watcher.openstack.org_watcherapis.yaml b/api/bases/watcher.openstack.org_watcherapis.yaml index 6a1ae8e..b27f85a 100644 --- a/api/bases/watcher.openstack.org_watcherapis.yaml +++ b/api/bases/watcher.openstack.org_watcherapis.yaml @@ -39,6 +39,10 @@ spec: spec: description: WatcherAPISpec defines the desired state of WatcherAPI properties: + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) + type: string databaseAccount: default: watcher description: DatabaseAccount - MariaDBAccount CR name used for watcher diff --git a/api/bases/watcher.openstack.org_watcherappliers.yaml b/api/bases/watcher.openstack.org_watcherappliers.yaml index 186d38b..6abda7c 100644 --- a/api/bases/watcher.openstack.org_watcherappliers.yaml +++ b/api/bases/watcher.openstack.org_watcherappliers.yaml @@ -39,9 +39,9 @@ spec: spec: description: WatcherApplierSpec defines the desired state of WatcherApplier properties: - foo: - description: Foo is an example field of WatcherApplier. Edit watcherapplier_types.go - to remove/update + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) type: string type: object status: diff --git a/api/bases/watcher.openstack.org_watcherdecisionengines.yaml b/api/bases/watcher.openstack.org_watcherdecisionengines.yaml index b3cf6c9..a417fcb 100644 --- a/api/bases/watcher.openstack.org_watcherdecisionengines.yaml +++ b/api/bases/watcher.openstack.org_watcherdecisionengines.yaml @@ -40,9 +40,9 @@ spec: spec: description: WatcherDecisionEngineSpec defines the desired state of WatcherDecisionEngine properties: - foo: - description: Foo is an example field of WatcherDecisionEngine. Edit - watcherdecisionengine_types.go to remove/update + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) type: string type: object status: diff --git a/api/bases/watcher.openstack.org_watchers.yaml b/api/bases/watcher.openstack.org_watchers.yaml index f11f730..88174e6 100644 --- a/api/bases/watcher.openstack.org_watchers.yaml +++ b/api/bases/watcher.openstack.org_watchers.yaml @@ -39,6 +39,12 @@ spec: spec: description: WatcherSpec defines the desired state of Watcher properties: + apiContainerImageURL: + description: APIContainerImageURL + type: string + applierContainerImageURL: + description: ApplierContainerImageURL + type: string databaseAccount: default: watcher description: DatabaseAccount - MariaDBAccount CR name used for watcher @@ -49,6 +55,9 @@ spec: MariaDB instance name Required to use the mariadb-operator instance to create the DB and user type: string + decisionengineContainerImageURL: + description: DecisionEngineContainerImageURL + type: string memcachedInstance: default: memcached description: MemcachedInstance is the name of the Memcached CR that @@ -82,7 +91,10 @@ spec: to register in keystone type: string required: + - apiContainerImageURL + - applierContainerImageURL - databaseInstance + - decisionengineContainerImageURL - rabbitMqClusterName type: object status: diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index d95da78..42cb0ae 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -16,6 +16,15 @@ limitations under the License. package v1beta1 +import "github.com/openstack-k8s-operators/lib-common/modules/common/util" + +// Container image fall-back defaults +const ( + WatcherAPIContainerImage = "quay.io/podified-antelope-centos9/openstack-watcher-api:current-podified" + WatcherDecisionEngineContainerImage = "quay.io/podified-antelope-centos9/openstack-watcher-decision-engine:current-podified" + WatcherApplierContainerImage = "quay.io/podified-antelope-centos9/openstack-watcher-applier:current-podified" +) + // WatcherCommon defines a spec based reusable for all the CRDs type WatcherCommon struct { @@ -70,3 +79,48 @@ type PasswordSelector struct { // Service - Selector to get the watcher service user password from the Secret Service string `json:"service"` } + +// WatcherSubCrsCommon +type WatcherSubCrsCommon struct { + // +kubebuilder:validation:Optional + // The service specific Container Image URL (will be set to environmental default if empty) + ContainerImage string `json:"containerImage"` +} + +type WatcherImages struct { + // +kubebuilder:validation:Required + // APIContainerImageURL + APIContainerImageURL string `json:"apiContainerImageURL"` + + // +kubebuilder:validation:Required + // DecisionEngineContainerImageURL + DecisionEngineContainerImageURL string `json:"decisionengineContainerImageURL"` + + // +kubebuilder:validation:Required + // ApplierContainerImageURL + ApplierContainerImageURL string `json:"applierContainerImageURL"` +} + +func (r *WatcherImages) Default(defaults WatcherDefaults) { + if r.APIContainerImageURL == "" { + r.APIContainerImageURL = defaults.APIContainerImageURL + } + if r.DecisionEngineContainerImageURL == "" { + r.DecisionEngineContainerImageURL = defaults.DecisionEngineContainerImageURL + } + if r.ApplierContainerImageURL == "" { + r.ApplierContainerImageURL = defaults.ApplierContainerImageURL + } +} + +// SetupDefaults - initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) + +func SetupDefaults() { + // Acquire environmental defaults and initialize Nova defaults with them + watcherDefaults := WatcherDefaults{ + APIContainerImageURL: util.GetEnvVar("WATCHER_API_IMAGE_URL_DEFAULT", WatcherAPIContainerImage), + ApplierContainerImageURL: util.GetEnvVar("WATCHER_APPLIER_IMAGE_URL_DEFAULT", WatcherApplierContainerImage), + DecisionEngineContainerImageURL: util.GetEnvVar("WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT", WatcherDecisionEngineContainerImage), + } + SetupWatcherDefaults(watcherDefaults) +} diff --git a/api/v1beta1/watcher_types.go b/api/v1beta1/watcher_types.go index 1dafb90..cc8dad8 100644 --- a/api/v1beta1/watcher_types.go +++ b/api/v1beta1/watcher_types.go @@ -27,6 +27,9 @@ type WatcherSpec struct { // Important: Run "make" to regenerate code after modifying this file WatcherTemplate `json:",inline"` + + // +kubebuilder:validation:Required + WatcherImages `json:",inline"` } // WatcherStatus defines the observed state of Watcher @@ -68,7 +71,3 @@ type WatcherList struct { func init() { SchemeBuilder.Register(&Watcher{}, &WatcherList{}) } - -// SetupDefaults - initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) -func SetupDefaults() { -} diff --git a/api/v1beta1/watcher_webhook.go b/api/v1beta1/watcher_webhook.go index 76ed051..af9a8f0 100644 --- a/api/v1beta1/watcher_webhook.go +++ b/api/v1beta1/watcher_webhook.go @@ -23,9 +23,23 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) +// WatcherDefaults - +type WatcherDefaults struct { + APIContainerImageURL string + DecisionEngineContainerImageURL string + ApplierContainerImageURL string +} + +var watcherDefaults WatcherDefaults + // log is for logging in this package. var watcherlog = logf.Log.WithName("watcher-resource") +func SetupWatcherDefaults(defaults WatcherDefaults) { + watcherDefaults = defaults + watcherlog.Info("Watcher defaults initialized", "defaults", defaults) +} + //+kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcher,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=mwatcher.kb.io,admissionReviewVersions=v1 var _ webhook.Defaulter = &Watcher{} @@ -34,6 +48,12 @@ var _ webhook.Defaulter = &Watcher{} func (r *Watcher) Default() { watcherlog.Info("default", "name", r.Name) + r.Spec.Default() +} + +// Default - set defaults for this WatcherCore spec. +func (spec *WatcherSpec) Default() { + spec.WatcherImages.Default(watcherDefaults) } //+kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcher,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=vwatcher.kb.io,admissionReviewVersions=v1 diff --git a/api/v1beta1/watcherapi_types.go b/api/v1beta1/watcherapi_types.go index de1b64f..c1b1eec 100644 --- a/api/v1beta1/watcherapi_types.go +++ b/api/v1beta1/watcherapi_types.go @@ -31,6 +31,8 @@ type WatcherAPISpec struct { // +kubebuilder:validation:Required // Secret containing all passwords / keys needed Secret string `json:"secret"` + + WatcherSubCrsCommon `json:",inline"` } // WatcherAPIStatus defines the observed state of WatcherAPI diff --git a/api/v1beta1/watcherapplier_types.go b/api/v1beta1/watcherapplier_types.go index b177d88..cf9b2cf 100644 --- a/api/v1beta1/watcherapplier_types.go +++ b/api/v1beta1/watcherapplier_types.go @@ -28,8 +28,7 @@ type WatcherApplierSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - // Foo is an example field of WatcherApplier. Edit watcherapplier_types.go to remove/update - Foo string `json:"foo,omitempty"` + WatcherSubCrsCommon `json:",inline"` } // WatcherApplierStatus defines the observed state of WatcherApplier diff --git a/api/v1beta1/watcherdecisionengine_types.go b/api/v1beta1/watcherdecisionengine_types.go index f42f9c7..4d0ae31 100644 --- a/api/v1beta1/watcherdecisionengine_types.go +++ b/api/v1beta1/watcherdecisionengine_types.go @@ -28,8 +28,7 @@ type WatcherDecisionEngineSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - // Foo is an example field of WatcherDecisionEngine. Edit watcherdecisionengine_types.go to remove/update - Foo string `json:"foo,omitempty"` + WatcherSubCrsCommon `json:",inline"` } // WatcherDecisionEngineStatus defines the observed state of WatcherDecisionEngine diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index cbdefed..9c737b5 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -130,6 +130,7 @@ func (in *WatcherAPIList) DeepCopyObject() runtime.Object { func (in *WatcherAPISpec) DeepCopyInto(out *WatcherAPISpec) { *out = *in out.WatcherCommon = in.WatcherCommon + out.WatcherSubCrsCommon = in.WatcherSubCrsCommon } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherAPISpec. @@ -226,6 +227,7 @@ func (in *WatcherApplierList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WatcherApplierSpec) DeepCopyInto(out *WatcherApplierSpec) { *out = *in + out.WatcherSubCrsCommon = in.WatcherSubCrsCommon } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherApplierSpec. @@ -331,6 +333,7 @@ func (in *WatcherDecisionEngineList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WatcherDecisionEngineSpec) DeepCopyInto(out *WatcherDecisionEngineSpec) { *out = *in + out.WatcherSubCrsCommon = in.WatcherSubCrsCommon } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherDecisionEngineSpec. @@ -358,6 +361,36 @@ func (in *WatcherDecisionEngineStatus) DeepCopy() *WatcherDecisionEngineStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WatcherDefaults) DeepCopyInto(out *WatcherDefaults) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherDefaults. +func (in *WatcherDefaults) DeepCopy() *WatcherDefaults { + if in == nil { + return nil + } + out := new(WatcherDefaults) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WatcherImages) DeepCopyInto(out *WatcherImages) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherImages. +func (in *WatcherImages) DeepCopy() *WatcherImages { + if in == nil { + return nil + } + out := new(WatcherImages) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WatcherList) DeepCopyInto(out *WatcherList) { *out = *in @@ -394,6 +427,7 @@ func (in *WatcherList) DeepCopyObject() runtime.Object { func (in *WatcherSpec) DeepCopyInto(out *WatcherSpec) { *out = *in out.WatcherTemplate = in.WatcherTemplate + out.WatcherImages = in.WatcherImages } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherSpec. @@ -428,6 +462,21 @@ func (in *WatcherStatus) DeepCopy() *WatcherStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WatcherSubCrsCommon) DeepCopyInto(out *WatcherSubCrsCommon) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherSubCrsCommon. +func (in *WatcherSubCrsCommon) DeepCopy() *WatcherSubCrsCommon { + if in == nil { + return nil + } + out := new(WatcherSubCrsCommon) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WatcherTemplate) DeepCopyInto(out *WatcherTemplate) { *out = *in diff --git a/config/crd/bases/watcher.openstack.org_watcherapis.yaml b/config/crd/bases/watcher.openstack.org_watcherapis.yaml index 6a1ae8e..b27f85a 100644 --- a/config/crd/bases/watcher.openstack.org_watcherapis.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherapis.yaml @@ -39,6 +39,10 @@ spec: spec: description: WatcherAPISpec defines the desired state of WatcherAPI properties: + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) + type: string databaseAccount: default: watcher description: DatabaseAccount - MariaDBAccount CR name used for watcher diff --git a/config/crd/bases/watcher.openstack.org_watcherappliers.yaml b/config/crd/bases/watcher.openstack.org_watcherappliers.yaml index 186d38b..6abda7c 100644 --- a/config/crd/bases/watcher.openstack.org_watcherappliers.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherappliers.yaml @@ -39,9 +39,9 @@ spec: spec: description: WatcherApplierSpec defines the desired state of WatcherApplier properties: - foo: - description: Foo is an example field of WatcherApplier. Edit watcherapplier_types.go - to remove/update + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) type: string type: object status: diff --git a/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml b/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml index b3cf6c9..a417fcb 100644 --- a/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml @@ -40,9 +40,9 @@ spec: spec: description: WatcherDecisionEngineSpec defines the desired state of WatcherDecisionEngine properties: - foo: - description: Foo is an example field of WatcherDecisionEngine. Edit - watcherdecisionengine_types.go to remove/update + containerImage: + description: The service specific Container Image URL (will be set + to environmental default if empty) type: string type: object status: diff --git a/config/crd/bases/watcher.openstack.org_watchers.yaml b/config/crd/bases/watcher.openstack.org_watchers.yaml index f11f730..88174e6 100644 --- a/config/crd/bases/watcher.openstack.org_watchers.yaml +++ b/config/crd/bases/watcher.openstack.org_watchers.yaml @@ -39,6 +39,12 @@ spec: spec: description: WatcherSpec defines the desired state of Watcher properties: + apiContainerImageURL: + description: APIContainerImageURL + type: string + applierContainerImageURL: + description: ApplierContainerImageURL + type: string databaseAccount: default: watcher description: DatabaseAccount - MariaDBAccount CR name used for watcher @@ -49,6 +55,9 @@ spec: MariaDB instance name Required to use the mariadb-operator instance to create the DB and user type: string + decisionengineContainerImageURL: + description: DecisionEngineContainerImageURL + type: string memcachedInstance: default: memcached description: MemcachedInstance is the name of the Memcached CR that @@ -82,7 +91,10 @@ spec: to register in keystone type: string required: + - apiContainerImageURL + - applierContainerImageURL - databaseInstance + - decisionengineContainerImageURL - rabbitMqClusterName type: object status: diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index d8f571d..c3f02b5 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -41,6 +41,9 @@ patches: # 'CERTMANAGER' needs to be enabled to use ca injection #- path: webhookcainjection_patch.yaml +# Injects our custom images (ENV variable settings) +- path: manager_default_images.yaml + # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. # Uncomment the following replacements to add the cert-manager CA injection annotations #replacements: diff --git a/config/default/manager_default_images.yaml b/config/default/manager_default_images.yaml new file mode 100644 index 0000000..f333aca --- /dev/null +++ b/config/default/manager_default_images.yaml @@ -0,0 +1,19 @@ +# This patch inject custom ENV settings to the manager container +# Used to set our default image locations +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + env: + - name: WATCHER_API_IMAGE_URL_DEFAULT + value: quay.io/podified-antelope-centos9/openstack-watcher-api:current-podified + - name: WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT + value: quay.io/podified-antelope-centos9/openstack-watcher-decision-engine:current-podified + - name: WATCHER_APPLIER_IMAGE_URL_DEFAULT + value: quay.io/podified-antelope-centos9/openstack-watcher-applier:current-podified diff --git a/main.go b/main.go index ad482cf..f8c4afa 100644 --- a/main.go +++ b/main.go @@ -150,6 +150,10 @@ func main() { if err != nil { os.Exit(1) } + + // Acquire environmental defaults and initialize operator defaults with them + watcherv1beta1.SetupDefaults() + checker := healthz.Ping // Setup webhooks if requested diff --git a/tests/functional/watcher_controller_test.go b/tests/functional/watcher_controller_test.go index 6553dea..0f065d9 100644 --- a/tests/functional/watcher_controller_test.go +++ b/tests/functional/watcher_controller_test.go @@ -6,6 +6,8 @@ import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" //revive:disable-next-line:dot-imports + "os" + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" keystonev1beta1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" @@ -20,6 +22,13 @@ var ( MinimalWatcherSpec = map[string]interface{}{ "databaseInstance": "openstack", } + + MinimalWatcherContainerSpec = map[string]interface{}{ + "databaseInstance": "openstack", + "apiContainerImageURL": "watcher-api-custom-image", + "applierContainerImageURL": "watcher-applier-custom-image", + "decisionengineContainerImageURL": "watcher-decision-engine-custom-image", + } ) var _ = Describe("Watcher controller with minimal spec values", func() { @@ -44,6 +53,13 @@ var _ = Describe("Watcher controller with minimal spec values", func() { Expect(Watcher.Status.ServiceID).Should(Equal("")) }) + It("It has the expected container image defaults", func() { + Watcher := GetWatcher(watcherTest.Instance) + Expect(Watcher.Spec.APIContainerImageURL).To(Equal(watcherv1beta1.WatcherAPIContainerImage)) + Expect(Watcher.Spec.DecisionEngineContainerImageURL).To(Equal(watcherv1beta1.WatcherDecisionEngineContainerImage)) + Expect(Watcher.Spec.ApplierContainerImageURL).To(Equal(watcherv1beta1.WatcherApplierContainerImage)) + }) + It("should have a finalizer", func() { // the reconciler loop adds the finalizer so we have to wait for // it to run @@ -371,4 +387,38 @@ var _ = Describe("Watcher controller", func() { }) }) + When("Watcher is created with container images defined in CR and env variables contains fake values", func() { + BeforeEach(func() { + // Set environment variables + os.Setenv("WATCHER_API_IMAGE_URL_DEFAULT", "watcher-api-custom-image-env") + os.Setenv("WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT", "watcher-decision-engine-custom-image-env") + os.Setenv("WATCHER_APPLIER_IMAGE_URL_DEFAULT", "watcher-applier-custom-image-env") + DeferCleanup(th.DeleteInstance, CreateWatcher(watcherTest.Instance, MinimalWatcherContainerSpec)) + }) + + It("It should have the fields coming from the spec", func() { + Watcher := GetWatcher(watcherTest.Instance) + Expect(Watcher.Spec.APIContainerImageURL).To(Equal("watcher-api-custom-image")) + Expect(Watcher.Spec.DecisionEngineContainerImageURL).To(Equal("watcher-decision-engine-custom-image")) + Expect(Watcher.Spec.ApplierContainerImageURL).To(Equal("watcher-applier-custom-image")) + }) + }) + + When("Watcher is created with not container images defined in CR and env variables contains fake value", func() { + BeforeEach(func() { + os.Setenv("WATCHER_API_IMAGE_URL_DEFAULT", "watcher-api-custom-image-env") + os.Setenv("WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT", "watcher-decision-engine-custom-image-env") + os.Setenv("WATCHER_APPLIER_IMAGE_URL_DEFAULT", "watcher-applier-custom-image-env") + DeferCleanup(th.DeleteInstance, CreateWatcher(watcherTest.Instance, MinimalWatcherSpec)) + }) + + It("It should have the fields coming from the environment variables", func() { + // Note(ChandanKumar): Fix it later why environment variables are not working. + Skip("Skipping this test case temporarily") + Watcher := GetWatcher(watcherTest.Instance) + Expect(Watcher.Spec.APIContainerImageURL).To(Equal("watcher-api-custom-image-env")) + Expect(Watcher.Spec.DecisionEngineContainerImageURL).To(Equal("watcher-decision-engine-custom-image-env")) + Expect(Watcher.Spec.ApplierContainerImageURL).To(Equal("watcher-applier-custom-image-env")) + }) + }) }) diff --git a/tests/kuttl/test-suites/default/watcher/01-assert.yaml b/tests/kuttl/test-suites/default/watcher/01-assert.yaml index 8c67fc8..bfa8b6a 100644 --- a/tests/kuttl/test-suites/default/watcher/01-assert.yaml +++ b/tests/kuttl/test-suites/default/watcher/01-assert.yaml @@ -5,6 +5,10 @@ metadata: - openstack.org/watcher name: watcher-kuttl namespace: watcher-kuttl-default +spec: + apiContainerImageURL: "quay.io/podified-antelope-centos9/openstack-watcher-api:current-podified" + decisionengineContainerImageURL: "quay.io/podified-antelope-centos9/openstack-watcher-decision-engine:current-podified" + applierContainerImageURL: "quay.io/podified-antelope-centos9/openstack-watcher-applier:current-podified" status: conditions: - message: Setup complete @@ -114,3 +118,24 @@ commands: oc exec -n watcher-kuttl-default openstackclient -- openstack service list -f value -c Name -c Type |[ $(grep -c ^watcher) == 1 ] SERVICEID=$(oc exec -n watcher-kuttl-default openstackclient -- openstack service list -f value -c Name -c Type -c ID | grep watcher| awk '{print $1}') [ $(oc get -n watcher-kuttl-default keystoneservice watcher -o jsonpath={.status.serviceID}) == $SERVICEID ] +--- +# Check for Container Image environment variables +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + set -euxo pipefail + env_variables=$(oc set env $(oc get pods -n openstack-operators -o name -l openstack.org/operator-name=watcher) -n openstack-operators --list) + counter = 0 + for i in ${env_variables}; do + if echo ${i} | grep '_URL_DEFAULT' &> /dev/null; then + echo ${i} + counter=$((counter + 1)) + fi + done + if [ ${counter} -lt 3 ]; then + echo "Error: Less than 3 _URL_DEFAULT variables found." + exit 1 + else + echo "Success: ${counter} _URL_DEFAULT variables found." + fi