diff --git a/api/bases/watcher.openstack.org_watcherapis.yaml b/api/bases/watcher.openstack.org_watcherapis.yaml index 2d146a4..e437604 100644 --- a/api/bases/watcher.openstack.org_watcherapis.yaml +++ b/api/bases/watcher.openstack.org_watcherapis.yaml @@ -39,10 +39,11 @@ spec: spec: description: WatcherAPISpec defines the desired state of WatcherAPI properties: - foo: - description: Foo is an example field of WatcherAPI. Edit watcherapi_types.go - to remove/update + containerImage: + description: ContainerImage - Watcher API Container Image URL type: string + required: + - containerImage type: object status: description: WatcherAPIStatus defines the observed state of WatcherAPI diff --git a/api/bases/watcher.openstack.org_watcherappliers.yaml b/api/bases/watcher.openstack.org_watcherappliers.yaml index 186d38b..a5b28af 100644 --- a/api/bases/watcher.openstack.org_watcherappliers.yaml +++ b/api/bases/watcher.openstack.org_watcherappliers.yaml @@ -39,10 +39,11 @@ 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: ContainerImage - Watcher Applier Container Image URL type: string + required: + - containerImage type: object status: description: WatcherApplierStatus defines the observed state of WatcherApplier diff --git a/api/bases/watcher.openstack.org_watcherdecisionengines.yaml b/api/bases/watcher.openstack.org_watcherdecisionengines.yaml index b3cf6c9..2b7ab3f 100644 --- a/api/bases/watcher.openstack.org_watcherdecisionengines.yaml +++ b/api/bases/watcher.openstack.org_watcherdecisionengines.yaml @@ -40,10 +40,12 @@ 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: ContainerImage - Watcher Decision Engine Container Image + URL type: string + required: + - containerImage type: object status: description: WatcherDecisionEngineStatus defines the observed state of diff --git a/api/bases/watcher.openstack.org_watchers.yaml b/api/bases/watcher.openstack.org_watchers.yaml index 4bfb5e8..bdc0dc5 100644 --- a/api/bases/watcher.openstack.org_watchers.yaml +++ b/api/bases/watcher.openstack.org_watchers.yaml @@ -39,6 +39,16 @@ spec: spec: description: WatcherSpec defines the desired state of Watcher properties: + apiContainerImageURL: + description: APIContainerImageURL + type: string + applierContainerImageURL: + description: DecisionEngineContainerImageURL + type: string + 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 @@ -49,6 +59,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 passwordSelectors: default: service: WatcherPassword @@ -66,7 +79,10 @@ spec: description: Secret containing all passwords / keys needed type: string required: + - apiContainerImageURL + - applierContainerImageURL - databaseInstance + - decisionengineContainerImageURL type: object status: description: WatcherStatus defines the observed state of Watcher diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index b1d422e..4e61747 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -16,11 +16,24 @@ limitations under the License. package v1beta1 +import "os" + +// Container image fall-back defaults +const ( + WatcherAPIContainerImage = "quay.io/podified-antelope-centos9/openstack-water-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" +) + // WatcherTemplate defines a spec based reusable for all the CRDs type WatcherTemplate struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file + // +kubebuilder:validation:Optional + // The service specific Container Image URL (will be set to environmental default if empty) + ContainerImage string `json:"containerImage"` + // +kubebuilder:validation:Optional // +kubebuilder:default=osp-secret // Secret containing all passwords / keys needed @@ -49,3 +62,37 @@ type PasswordSelector struct { // Service - Selector to get the watcher service user password from the Secret Service string `json:"service"` } + +type WatcherImages struct { + // +kubebuilder:validation:Required + // APIContainerImageURL + APIContainerImageURL string `json:"apiContainerImageURL"` + + // +kubebuilder:validation:Required + // DecisionEngineContainerImageURL + DecisionEngineContainerImageURL string `json:"decisionengineContainerImageURL"` + + // +kubebuilder:validation:Required + // DecisionEngineContainerImageURL + ApplierContainerImageURL string `json:"applierContainerImageURL"` +} + +// GetEnvDefault - Get the value associated with key from environment variables, but use baseDefault as a value in the case of an empty string +func GetEnvDefault(key string, baseDefault string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return baseDefault +} + +// 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: GetEnvDefault("WATCHER_API_IMAGE_URL_DEFAULT", WatcherAPIContainerImage), + ApplierContainerImageURL: GetEnvDefault("WATCHER_APPLIER_IMAGE_URL_DEFAULT", WatcherApplierContainerImage), + DecisionEngineContainerImageURL: GetEnvDefault("WATCHER_DECISION_ENGINE_IMAGE_URI_DEFAULT", WatcherDecisionEngineContainerImage), + } + SetupWatcherDefaults(watcherDefaults) +} diff --git a/api/v1beta1/watcher_types.go b/api/v1beta1/watcher_types.go index 5b5b887..820c933 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 @@ -65,7 +68,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..4104cb7 100644 --- a/api/v1beta1/watcher_webhook.go +++ b/api/v1beta1/watcher_webhook.go @@ -23,9 +23,29 @@ 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") +// SetupWatcherDefaults - initialize Watcher spec defaults for use with either internal or external webhooks +func SetupWatcherDefaults(defaults WatcherDefaults) { + watcherDefaults = defaults + watcherlog.Info("Watcher defaults initialized", "defaults", defaults) +} + +// SetupDefaults - initialize Watcher spec defaults for use with either internal or external webhooks +func (spec *WatcherSpec) SetupDefaults(defaults WatcherDefaults) { + watcherDefaults = 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{} diff --git a/api/v1beta1/watcherapi_types.go b/api/v1beta1/watcherapi_types.go index 8c63bbf..5b7f94e 100644 --- a/api/v1beta1/watcherapi_types.go +++ b/api/v1beta1/watcherapi_types.go @@ -28,8 +28,9 @@ type WatcherAPISpec 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 WatcherAPI. Edit watcherapi_types.go to remove/update - Foo string `json:"foo,omitempty"` + // +kubebuilder:validation:Required + // ContainerImage - Watcher API Container Image URL + ContainerImage string `json:"containerImage"` } // WatcherAPIStatus defines the observed state of WatcherAPI diff --git a/api/v1beta1/watcherapplier_types.go b/api/v1beta1/watcherapplier_types.go index b177d88..2c0cdb0 100644 --- a/api/v1beta1/watcherapplier_types.go +++ b/api/v1beta1/watcherapplier_types.go @@ -28,8 +28,9 @@ 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"` + // +kubebuilder:validation:Required + // ContainerImage - Watcher Applier Container Image URL + ContainerImage string `json:"containerImage"` } // WatcherApplierStatus defines the observed state of WatcherApplier diff --git a/api/v1beta1/watcherdecisionengine_types.go b/api/v1beta1/watcherdecisionengine_types.go index f42f9c7..07a0044 100644 --- a/api/v1beta1/watcherdecisionengine_types.go +++ b/api/v1beta1/watcherdecisionengine_types.go @@ -28,8 +28,9 @@ 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"` + // +kubebuilder:validation:Required + // ContainerImage - Watcher Decision Engine Container Image URL + ContainerImage string `json:"containerImage"` } // WatcherDecisionEngineStatus defines the observed state of WatcherDecisionEngine diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 9d3cf2b..73f6821 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -334,6 +334,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 @@ -370,6 +400,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. diff --git a/config/crd/bases/watcher.openstack.org_watcherapis.yaml b/config/crd/bases/watcher.openstack.org_watcherapis.yaml index 2d146a4..e437604 100644 --- a/config/crd/bases/watcher.openstack.org_watcherapis.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherapis.yaml @@ -39,10 +39,11 @@ spec: spec: description: WatcherAPISpec defines the desired state of WatcherAPI properties: - foo: - description: Foo is an example field of WatcherAPI. Edit watcherapi_types.go - to remove/update + containerImage: + description: ContainerImage - Watcher API Container Image URL type: string + required: + - containerImage type: object status: description: WatcherAPIStatus defines the observed state of WatcherAPI diff --git a/config/crd/bases/watcher.openstack.org_watcherappliers.yaml b/config/crd/bases/watcher.openstack.org_watcherappliers.yaml index 186d38b..a5b28af 100644 --- a/config/crd/bases/watcher.openstack.org_watcherappliers.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherappliers.yaml @@ -39,10 +39,11 @@ 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: ContainerImage - Watcher Applier Container Image URL type: string + required: + - containerImage type: object status: description: WatcherApplierStatus defines the observed state of WatcherApplier diff --git a/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml b/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml index b3cf6c9..2b7ab3f 100644 --- a/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml +++ b/config/crd/bases/watcher.openstack.org_watcherdecisionengines.yaml @@ -40,10 +40,12 @@ 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: ContainerImage - Watcher Decision Engine Container Image + URL type: string + required: + - containerImage type: object status: description: WatcherDecisionEngineStatus defines the observed state of diff --git a/config/crd/bases/watcher.openstack.org_watchers.yaml b/config/crd/bases/watcher.openstack.org_watchers.yaml index 4bfb5e8..bdc0dc5 100644 --- a/config/crd/bases/watcher.openstack.org_watchers.yaml +++ b/config/crd/bases/watcher.openstack.org_watchers.yaml @@ -39,6 +39,16 @@ spec: spec: description: WatcherSpec defines the desired state of Watcher properties: + apiContainerImageURL: + description: APIContainerImageURL + type: string + applierContainerImageURL: + description: DecisionEngineContainerImageURL + type: string + 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 @@ -49,6 +59,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 passwordSelectors: default: service: WatcherPassword @@ -66,7 +79,10 @@ spec: description: Secret containing all passwords / keys needed type: string required: + - apiContainerImageURL + - applierContainerImageURL - databaseInstance + - decisionengineContainerImageURL type: object status: description: WatcherStatus defines the observed state of Watcher 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/main.go b/main.go index 69bc928..57fe41b 100644 --- a/main.go +++ b/main.go @@ -145,8 +145,17 @@ func main() { os.Exit(1) } checker := healthz.Ping - // Setup webhooks if requested + // Acquire environmental defaults and initialize Cinder defaults with them + watcherDefaults := watcherv1beta1.WatcherDefaults{ + APIContainerImageURL: os.Getenv("WATCHER_API_IMAGE_URL_DEFAULT"), + DecisionEngineContainerImageURL: os.Getenv("WATCHER_DECISION_ENGINE_IMAGE_URL_DEFAULT"), + ApplierContainerImageURL: os.Getenv("WATCHER_APPLIER_IMAGE_URL_DEFAULT"), + } + + (&watcherv1beta1.Watcher{}).Spec.SetupDefaults(watcherDefaults) + + // Setup webhooks if requested if strings.ToLower(os.Getenv("ENABLE_WEBHOOKS")) != "false" { if err = (&watcherv1beta1.Watcher{}).SetupWebhookWithManager(mgr); err != nil {