diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index 46148daaa..4eac7befd 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -128,10 +128,12 @@ type OpenStackControlPlaneSpec struct { // Memcached - Parameters related to the Memcached service Memcached MemcachedSection `json:"memcached,omitempty"` + // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Ovn - Overrides to use when creating the OVN Services Ovn OvnSection `json:"ovn,omitempty"` + // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Neutron - Overrides to use when creating the Neutron Service Neutron NeutronSection `json:"neutron,omitempty"` @@ -151,6 +153,8 @@ type OpenStackControlPlaneSpec struct { // Ironic - Parameters related to the Ironic services Ironic IronicSection `json:"ironic,omitempty"` + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Manila - Parameters related to the Manila service Manila ManilaSection `json:"manila,omitempty"` @@ -160,18 +164,27 @@ type OpenStackControlPlaneSpec struct { Horizon HorizonSection `json:"horizon,omitempty"` // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Telemetry - Parameters related to the OpenStack Telemetry services Telemetry TelemetrySection `json:"telemetry,omitempty"` + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Swift - Parameters related to the Swift service Swift SwiftSection `json:"swift,omitempty"` + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Octavia - Parameters related to the Octavia service Octavia OctaviaSection `json:"octavia,omitempty"` + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Designate - Parameters related to the Designate service Designate DesignateSection `json:"designate,omitempty"` + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec // Barbican - Parameters related to the Barbican service Barbican BarbicanSection `json:"barbican,omitempty"` @@ -322,7 +335,7 @@ type DNSMasqSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the DNSMasq service - Template networkv1.DNSMasqSpec `json:"template,omitempty"` + Template *networkv1.DNSMasqSpec `json:"template,omitempty"` } // KeystoneSection defines the desired state of Keystone service @@ -336,7 +349,7 @@ type KeystoneSection struct { // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Keystone service - Template keystonev1.KeystoneAPISpecCore `json:"template,omitempty"` + Template *keystonev1.KeystoneAPISpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -376,7 +389,7 @@ type PlacementSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Placement API - Template placementv1.PlacementAPISpecCore `json:"template,omitempty"` + Template *placementv1.PlacementAPISpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -395,7 +408,7 @@ type GlanceSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Glance Service - Template glancev1.GlanceSpecCore `json:"template,omitempty"` + Template *glancev1.GlanceSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -414,7 +427,7 @@ type CinderSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating Cinder Resources - Template cinderv1.CinderSpecCore `json:"template,omitempty"` + Template *cinderv1.CinderSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -433,7 +446,7 @@ type GaleraSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Templates - Overrides to use when creating the Galera databases - Templates map[string]mariadbv1.GaleraSpecCore `json:"templates,omitempty"` + Templates *map[string]mariadbv1.GaleraSpecCore `json:"templates,omitempty"` } // RabbitmqSection defines the desired state of RabbitMQ service @@ -447,7 +460,7 @@ type RabbitmqSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Templates - Overrides to use when creating the Rabbitmq clusters - Templates map[string]RabbitmqTemplate `json:"templates"` + Templates *map[string]RabbitmqTemplate `json:"templates"` } // MemcachedSection defines the desired state of Memcached services @@ -461,7 +474,7 @@ type MemcachedSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Templates - Overrides to use when creating the Memcached databases - Templates map[string]memcachedv1.MemcachedSpecCore `json:"templates,omitempty"` + Templates *map[string]memcachedv1.MemcachedSpecCore `json:"templates,omitempty"` } // RabbitmqTemplate definition @@ -483,7 +496,7 @@ type OvnSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the OVN services - Template OvnResources `json:"template,omitempty"` + Template *OvnResources `json:"template,omitempty"` } // OvnResources defines the desired state of OVN services @@ -515,7 +528,7 @@ type NeutronSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Neutron Service - Template neutronv1.NeutronAPISpecCore `json:"template,omitempty"` + Template *neutronv1.NeutronAPISpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -534,7 +547,7 @@ type NovaSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Nova services - Template novav1.NovaSpec `json:"template,omitempty"` + Template *novav1.NovaSpec `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -566,7 +579,7 @@ type HeatSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Heat services - Template heatv1.HeatSpecCore `json:"template,omitempty"` + Template *heatv1.HeatSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -590,7 +603,7 @@ type IronicSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Ironic services - Template ironicv1.IronicSpecCore `json:"template,omitempty"` + Template *ironicv1.IronicSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -612,8 +625,9 @@ type ManilaSection struct { Enabled bool `json:"enabled"` // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating Manila Resources - Template manilav1.ManilaSpecCore `json:"template,omitempty"` + Template *manilav1.ManilaSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -629,8 +643,9 @@ type HorizonSection struct { Enabled bool `json:"enabled"` // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Horizon services - Template horizonv1.HorizonSpecCore `json:"template,omitempty"` + Template *horizonv1.HorizonSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -649,7 +664,7 @@ type TelemetrySection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the OpenStack Telemetry services - Template telemetryv1.TelemetrySpecCore `json:"template,omitempty"` + Template *telemetryv1.TelemetrySpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -678,7 +693,7 @@ type SwiftSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating Swift Resources - Template swiftv1.SwiftSpecCore `json:"template,omitempty"` + Template *swiftv1.SwiftSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -697,7 +712,7 @@ type OctaviaSection struct { // +kubebuilder:valdiation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating Octavia Resources - Template octaviav1.OctaviaSpecCore `json:"template,omitempty"` + Template *octaviav1.OctaviaSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -716,7 +731,7 @@ type DesignateSection struct { // +kubebuilder:valdiation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating Designate Resources - Template designatev1.DesignateSpecCore `json:"template,omitempty"` + Template *designatev1.DesignateSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec @@ -735,7 +750,7 @@ type BarbicanSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Barbican Service - Template barbicanv1.BarbicanSpecCore `json:"template,omitempty"` + Template *barbicanv1.BarbicanSpecCore `json:"template,omitempty"` // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec diff --git a/apis/core/v1beta1/openstackcontrolplane_webhook.go b/apis/core/v1beta1/openstackcontrolplane_webhook.go index 99464fbf1..4c37abd3c 100644 --- a/apis/core/v1beta1/openstackcontrolplane_webhook.go +++ b/apis/core/v1beta1/openstackcontrolplane_webhook.go @@ -21,16 +21,36 @@ import ( "fmt" "strings" + keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common/route" + mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" + placementv1 "github.com/openstack-k8s-operators/placement-operator/api/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + barbicanv1 "github.com/openstack-k8s-operators/barbican-operator/api/v1beta1" + cinderv1 "github.com/openstack-k8s-operators/cinder-operator/api/v1beta1" + designatev1 "github.com/openstack-k8s-operators/designate-operator/api/v1beta1" + glancev1 "github.com/openstack-k8s-operators/glance-operator/api/v1beta1" + heatv1 "github.com/openstack-k8s-operators/heat-operator/api/v1beta1" + horizonv1 "github.com/openstack-k8s-operators/horizon-operator/api/v1beta1" + memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" + networkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1" + ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" + manilav1 "github.com/openstack-k8s-operators/manila-operator/api/v1beta1" + neutronv1 "github.com/openstack-k8s-operators/neutron-operator/api/v1beta1" + novav1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1" + octaviav1 "github.com/openstack-k8s-operators/octavia-operator/api/v1beta1" + swiftv1 "github.com/openstack-k8s-operators/swift-operator/api/v1beta1" + telemetryv1 "github.com/openstack-k8s-operators/telemetry-operator/api/v1beta1" ) var ctlplaneWebhookClient client.Client @@ -158,8 +178,8 @@ func (r *OpenStackControlPlane) checkDepsEnabled(name string) string { switch name { case "Keystone": - if !((r.Spec.Galera.Enabled) && r.Spec.Memcached.Enabled) { - reqs = "Galera, Memcached" + if !((r.Spec.Galera.Enabled) && r.Spec.Memcached.Enabled && r.Spec.Rabbitmq.Enabled) { + reqs = "Galera, Memcached, RabbitMQ" } case "Glance": if !((r.Spec.Galera.Enabled) && r.Spec.Memcached.Enabled && r.Spec.Keystone.Enabled) { @@ -287,55 +307,94 @@ func (r *OpenStackControlPlane) ValidateUpdateServices(old OpenStackControlPlane // Call internal validation logic for individual service operators if r.Spec.Keystone.Enabled { - errors = append(errors, r.Spec.Keystone.Template.ValidateUpdate(old.Keystone.Template, basePath.Child("keystone").Child("template"))...) + if old.Keystone.Template == nil { + old.Keystone.Template = &keystonev1.KeystoneAPISpecCore{} + } + errors = append(errors, r.Spec.Keystone.Template.ValidateUpdate(*old.Keystone.Template, basePath.Child("keystone").Child("template"))...) } if r.Spec.Ironic.Enabled { - errors = append(errors, r.Spec.Ironic.Template.ValidateUpdate(old.Ironic.Template, basePath.Child("ironic").Child("template"))...) + if old.Ironic.Template == nil { + old.Ironic.Template = &ironicv1.IronicSpecCore{} + } + errors = append(errors, r.Spec.Ironic.Template.ValidateUpdate(*old.Ironic.Template, basePath.Child("ironic").Child("template"))...) } if r.Spec.Nova.Enabled { - errors = append(errors, r.Spec.Nova.Template.ValidateUpdate(old.Nova.Template, basePath.Child("nova").Child("template"))...) + if old.Nova.Template == nil { + old.Nova.Template = &novav1.NovaSpec{} + } + errors = append(errors, r.Spec.Nova.Template.ValidateUpdate(*old.Nova.Template, basePath.Child("nova").Child("template"))...) } if r.Spec.Placement.Enabled { - errors = append(errors, r.Spec.Placement.Template.ValidateUpdate(old.Placement.Template, basePath.Child("placement").Child("template"))...) + if old.Placement.Template == nil { + old.Placement.Template = &placementv1.PlacementAPISpecCore{} + } + errors = append(errors, r.Spec.Placement.Template.ValidateUpdate(*old.Placement.Template, basePath.Child("placement").Child("template"))...) } if r.Spec.Barbican.Enabled { - errors = append(errors, r.Spec.Barbican.Template.ValidateUpdate(old.Barbican.Template, basePath.Child("barbican").Child("template"))...) + if old.Barbican.Template == nil { + old.Barbican.Template = &barbicanv1.BarbicanSpecCore{} + } + errors = append(errors, r.Spec.Barbican.Template.ValidateUpdate(*old.Barbican.Template, basePath.Child("barbican").Child("template"))...) } if r.Spec.Neutron.Enabled { - errors = append(errors, r.Spec.Neutron.Template.ValidateUpdate(old.Neutron.Template, basePath.Child("neutron").Child("template"))...) + if old.Neutron.Template == nil { + old.Neutron.Template = &neutronv1.NeutronAPISpecCore{} + } + errors = append(errors, r.Spec.Neutron.Template.ValidateUpdate(*old.Neutron.Template, basePath.Child("neutron").Child("template"))...) } if r.Spec.Glance.Enabled { - errors = append(errors, r.Spec.Glance.Template.ValidateUpdate(old.Glance.Template, basePath.Child("glance").Child("template"))...) + if old.Glance.Template == nil { + old.Glance.Template = &glancev1.GlanceSpecCore{} + } + errors = append(errors, r.Spec.Glance.Template.ValidateUpdate(*old.Glance.Template, basePath.Child("glance").Child("template"))...) } if r.Spec.Cinder.Enabled { - errors = append(errors, r.Spec.Cinder.Template.ValidateUpdate(old.Cinder.Template, basePath.Child("cinder").Child("template"))...) + if old.Cinder.Template == nil { + old.Cinder.Template = &cinderv1.CinderSpecCore{} + } + errors = append(errors, r.Spec.Cinder.Template.ValidateUpdate(*old.Cinder.Template, basePath.Child("cinder").Child("template"))...) } if r.Spec.Heat.Enabled { - errors = append(errors, r.Spec.Heat.Template.ValidateUpdate(old.Heat.Template, basePath.Child("heat").Child("template"))...) + if old.Heat.Template == nil { + old.Heat.Template = &heatv1.HeatSpecCore{} + } + errors = append(errors, r.Spec.Heat.Template.ValidateUpdate(*old.Heat.Template, basePath.Child("heat").Child("template"))...) } if r.Spec.Manila.Enabled { - errors = append(errors, r.Spec.Manila.Template.ValidateUpdate(old.Manila.Template, basePath.Child("manila").Child("template"))...) + if old.Manila.Template == nil { + old.Manila.Template = &manilav1.ManilaSpecCore{} + } + errors = append(errors, r.Spec.Manila.Template.ValidateUpdate(*old.Manila.Template, basePath.Child("manila").Child("template"))...) } if r.Spec.Swift.Enabled { - errors = append(errors, r.Spec.Swift.Template.ValidateUpdate(old.Swift.Template, basePath.Child("swift").Child("template"))...) + if old.Swift.Template == nil { + old.Swift.Template = &swiftv1.SwiftSpecCore{} + } + errors = append(errors, r.Spec.Swift.Template.ValidateUpdate(*old.Swift.Template, basePath.Child("swift").Child("template"))...) } if r.Spec.Octavia.Enabled { - errors = append(errors, r.Spec.Octavia.Template.ValidateUpdate(old.Octavia.Template, basePath.Child("octavia").Child("template"))...) + if old.Octavia.Template == nil { + old.Octavia.Template = &octaviav1.OctaviaSpecCore{} + } + errors = append(errors, r.Spec.Octavia.Template.ValidateUpdate(*old.Octavia.Template, basePath.Child("octavia").Child("template"))...) } if r.Spec.Designate.Enabled { - errors = append(errors, r.Spec.Designate.Template.ValidateUpdate(old.Designate.Template, basePath.Child("designate").Child("template"))...) + if old.Designate.Template == nil { + old.Designate.Template = &designatev1.DesignateSpecCore{} + } + errors = append(errors, r.Spec.Designate.Template.ValidateUpdate(*old.Designate.Template, basePath.Child("designate").Child("template"))...) } return errors @@ -463,116 +522,221 @@ func setOverrideSpec(override **route.OverrideSpec, anno map[string]string) { // DefaultServices - common function for calling individual services' defaulting functions func (r *OpenStackControlPlane) DefaultServices() { // Cinder - r.Spec.Cinder.Template.Default() - initializeOverrideSpec(&r.Spec.Cinder.APIOverride.Route, true) - r.Spec.Cinder.Template.SetDefaultRouteAnnotations(r.Spec.Cinder.APIOverride.Route.Annotations) + if r.Spec.Cinder.Enabled || r.Spec.Cinder.Template != nil { + if r.Spec.Cinder.Template == nil { + r.Spec.Cinder.Template = &cinderv1.CinderSpecCore{} + } + r.Spec.Cinder.Template.Default() + initializeOverrideSpec(&r.Spec.Cinder.APIOverride.Route, true) + r.Spec.Cinder.Template.SetDefaultRouteAnnotations(r.Spec.Cinder.APIOverride.Route.Annotations) + } // Galera - for key, template := range r.Spec.Galera.Templates { - if template.StorageClass == "" { - template.StorageClass = r.Spec.StorageClass + if r.Spec.Galera.Enabled || r.Spec.Galera.Templates != nil { + if r.Spec.Galera.Templates == nil { + r.Spec.Galera.Templates = ptr.To(map[string]mariadbv1.GaleraSpecCore{}) } - if template.Secret == "" { - template.Secret = r.Spec.Secret + + for key, template := range *r.Spec.Galera.Templates { + if template.StorageClass == "" { + template.StorageClass = r.Spec.StorageClass + } + if template.Secret == "" { + template.Secret = r.Spec.Secret + } + template.Default() + // By-value copy, need to update + (*r.Spec.Galera.Templates)[key] = template } - template.Default() - // By-value copy, need to update - r.Spec.Galera.Templates[key] = template } // Glance - r.Spec.Glance.Template.Default() - - // initialize the main APIOverride struct - if r.Spec.Glance.APIOverride == nil { - r.Spec.Glance.APIOverride = map[string]Override{} - } - for name, glanceAPI := range r.Spec.Glance.Template.GlanceAPIs { - var override Override - var ok bool - - if override, ok = r.Spec.Glance.APIOverride[name]; !ok { - override = Override{} + if r.Spec.Glance.Enabled || r.Spec.Glance.Template != nil { + if r.Spec.Glance.Template == nil { + r.Spec.Glance.Template = &glancev1.GlanceSpecCore{} + } + r.Spec.Glance.Template.Default() + // initialize the main APIOverride struct + if r.Spec.Glance.APIOverride == nil { + r.Spec.Glance.APIOverride = map[string]Override{} + } + for name, glanceAPI := range r.Spec.Glance.Template.GlanceAPIs { + var override Override + var ok bool + + if override, ok = r.Spec.Glance.APIOverride[name]; !ok { + override = Override{} + } + initializeOverrideSpec(&override.Route, true) + glanceAPI.SetDefaultRouteAnnotations(override.Route.Annotations) + r.Spec.Glance.APIOverride[name] = override } - initializeOverrideSpec(&override.Route, true) - glanceAPI.SetDefaultRouteAnnotations(override.Route.Annotations) - r.Spec.Glance.APIOverride[name] = override } // Ironic - // Default Secret - if r.Spec.Ironic.Template.Secret == "" { - r.Spec.Ironic.Template.Secret = r.Spec.Secret - } - // Default DatabaseInstance - if r.Spec.Ironic.Template.DatabaseInstance == "" { - r.Spec.Ironic.Template.DatabaseInstance = "openstack" - } - // Default StorageClass - if r.Spec.Ironic.Template.StorageClass == "" { - r.Spec.Ironic.Template.StorageClass = r.Spec.StorageClass + if r.Spec.Ironic.Enabled || r.Spec.Ironic.Template != nil { + if r.Spec.Ironic.Template == nil { + r.Spec.Ironic.Template = &ironicv1.IronicSpecCore{} + } + + // Default Secret + if r.Spec.Ironic.Template.Secret == "" { + r.Spec.Ironic.Template.Secret = r.Spec.Secret + } + // Default DatabaseInstance + if r.Spec.Ironic.Template.DatabaseInstance == "" { + r.Spec.Ironic.Template.DatabaseInstance = "openstack" + } + // Default StorageClass + if r.Spec.Ironic.Template.StorageClass == "" { + r.Spec.Ironic.Template.StorageClass = r.Spec.StorageClass + } + r.Spec.Ironic.Template.Default() } - r.Spec.Ironic.Template.Default() // Keystone - r.Spec.Keystone.Template.Default() + if r.Spec.Keystone.Enabled || r.Spec.Keystone.Template != nil { + if r.Spec.Keystone.Template == nil { + r.Spec.Keystone.Template = &keystonev1.KeystoneAPISpecCore{} + } + r.Spec.Keystone.Template.Default() + } // Manila - r.Spec.Manila.Template.Default() - initializeOverrideSpec(&r.Spec.Manila.APIOverride.Route, true) - r.Spec.Manila.Template.SetDefaultRouteAnnotations(r.Spec.Manila.APIOverride.Route.Annotations) + if r.Spec.Manila.Enabled || r.Spec.Manila.Template != nil { + if r.Spec.Manila.Template == nil { + r.Spec.Manila.Template = &manilav1.ManilaSpecCore{} + } + r.Spec.Manila.Template.Default() + initializeOverrideSpec(&r.Spec.Manila.APIOverride.Route, true) + r.Spec.Manila.Template.SetDefaultRouteAnnotations(r.Spec.Manila.APIOverride.Route.Annotations) + } // Memcached - for key, template := range r.Spec.Memcached.Templates { - template.Default() - // By-value copy, need to update - r.Spec.Memcached.Templates[key] = template + if r.Spec.Memcached.Enabled || r.Spec.Memcached.Templates != nil { + if r.Spec.Memcached.Templates == nil { + r.Spec.Memcached.Templates = ptr.To(map[string]memcachedv1.MemcachedSpecCore{}) + } + + for key, template := range *r.Spec.Memcached.Templates { + template.Default() + // By-value copy, need to update + (*r.Spec.Memcached.Templates)[key] = template + } } // Neutron - r.Spec.Neutron.Template.Default() - setOverrideSpec(&r.Spec.Neutron.APIOverride.Route, r.Spec.Neutron.Template.GetDefaultRouteAnnotations()) + if r.Spec.Neutron.Enabled || r.Spec.Neutron.Template != nil { + if r.Spec.Neutron.Template == nil { + r.Spec.Neutron.Template = &neutronv1.NeutronAPISpecCore{} + } + r.Spec.Neutron.Template.Default() + setOverrideSpec(&r.Spec.Neutron.APIOverride.Route, r.Spec.Neutron.Template.GetDefaultRouteAnnotations()) + } // Nova - r.Spec.Nova.Template.Default() + if r.Spec.Nova.Enabled || r.Spec.Nova.Template != nil { + if r.Spec.Nova.Template == nil { + r.Spec.Nova.Template = &novav1.NovaSpec{} + } + r.Spec.Nova.Template.Default() + } // OVN - for key, template := range r.Spec.Ovn.Template.OVNDBCluster { - template.Default() - // By-value copy, need to update - r.Spec.Ovn.Template.OVNDBCluster[key] = template - } + if r.Spec.Ovn.Enabled || r.Spec.Ovn.Template != nil { + if r.Spec.Ovn.Template == nil { + r.Spec.Ovn.Template = &OvnResources{} + } + + for key, template := range r.Spec.Ovn.Template.OVNDBCluster { + template.Default() + // By-value copy, need to update + r.Spec.Ovn.Template.OVNDBCluster[key] = template + } - r.Spec.Ovn.Template.OVNNorthd.Default() - r.Spec.Ovn.Template.OVNController.Default() + r.Spec.Ovn.Template.OVNNorthd.Default() + r.Spec.Ovn.Template.OVNController.Default() + } // Placement - r.Spec.Placement.Template.Default() + if r.Spec.Placement.Enabled || r.Spec.Placement.Template != nil { + if r.Spec.Placement.Template == nil { + r.Spec.Placement.Template = &placementv1.PlacementAPISpecCore{} + } + r.Spec.Placement.Template.Default() + } // DNS - r.Spec.DNS.Template.Default() + if r.Spec.DNS.Enabled || r.Spec.DNS.Template != nil { + if r.Spec.DNS.Template == nil { + r.Spec.DNS.Template = &networkv1.DNSMasqSpec{} + } + + r.Spec.DNS.Template.Default() + } // Telemetry - r.Spec.Telemetry.Template.Default() + if r.Spec.Telemetry.Enabled || r.Spec.Telemetry.Template != nil { + if r.Spec.Telemetry.Template == nil { + r.Spec.Telemetry.Template = &telemetryv1.TelemetrySpecCore{} + } + r.Spec.Telemetry.Template.Default() + } // Heat - r.Spec.Heat.Template.Default() + if r.Spec.Heat.Enabled || r.Spec.Heat.Template != nil { + if r.Spec.Heat.Template == nil { + r.Spec.Heat.Template = &heatv1.HeatSpecCore{} + } + r.Spec.Heat.Template.Default() + } // Swift - if r.Spec.Swift.Template.SwiftStorage.StorageClass == "" { - r.Spec.Swift.Template.SwiftStorage.StorageClass = r.Spec.StorageClass - } + if r.Spec.Swift.Enabled || r.Spec.Swift.Template != nil { + if r.Spec.Swift.Template == nil { + r.Spec.Swift.Template = &swiftv1.SwiftSpecCore{} + } - r.Spec.Swift.Template.Default() + if r.Spec.Swift.Template.SwiftStorage.StorageClass == "" { + r.Spec.Swift.Template.SwiftStorage.StorageClass = r.Spec.StorageClass + } + + r.Spec.Swift.Template.Default() + } // Horizon - r.Spec.Horizon.Template.Default() + if r.Spec.Horizon.Enabled || r.Spec.Horizon.Template != nil { + if r.Spec.Horizon.Template == nil { + r.Spec.Horizon.Template = &horizonv1.HorizonSpecCore{} + } + + r.Spec.Horizon.Template.Default() + } // Octavia - r.Spec.Octavia.Template.Default() + if r.Spec.Octavia.Enabled || r.Spec.Octavia.Template != nil { + if r.Spec.Octavia.Template == nil { + r.Spec.Octavia.Template = &octaviav1.OctaviaSpecCore{} + } + + r.Spec.Octavia.Template.Default() + } // Barbican - r.Spec.Barbican.Template.Default() + if r.Spec.Barbican.Enabled || r.Spec.Barbican.Template != nil { + if r.Spec.Barbican.Template == nil { + r.Spec.Barbican.Template = &barbicanv1.BarbicanSpecCore{} + } + r.Spec.Barbican.Template.Default() + } + + // Designate + if r.Spec.Designate.Enabled || r.Spec.Designate.Template != nil { + if r.Spec.Designate.Template == nil { + r.Spec.Designate.Template = &designatev1.DesignateSpecCore{} + } + r.Spec.Designate.Template.Default() + } } // DefaultLabel - adding default label to the OpenStackControlPlane diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index 5e8d1a0a0..9e80fa89e 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -22,12 +22,28 @@ limitations under the License. package v1beta1 import ( + barbican_operatorapiv1beta1 "github.com/openstack-k8s-operators/barbican-operator/api/v1beta1" + cinder_operatorapiv1beta1 "github.com/openstack-k8s-operators/cinder-operator/api/v1beta1" + designate_operatorapiv1beta1 "github.com/openstack-k8s-operators/designate-operator/api/v1beta1" + glance_operatorapiv1beta1 "github.com/openstack-k8s-operators/glance-operator/api/v1beta1" + heat_operatorapiv1beta1 "github.com/openstack-k8s-operators/heat-operator/api/v1beta1" + horizon_operatorapiv1beta1 "github.com/openstack-k8s-operators/horizon-operator/api/v1beta1" memcachedv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" + networkv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1" + ironic_operatorapiv1beta1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" + apiv1beta1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/route" "github.com/openstack-k8s-operators/lib-common/modules/storage" - apiv1beta1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" + manila_operatorapiv1beta1 "github.com/openstack-k8s-operators/manila-operator/api/v1beta1" + mariadb_operatorapiv1beta1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" + neutron_operatorapiv1beta1 "github.com/openstack-k8s-operators/neutron-operator/api/v1beta1" + nova_operatorapiv1beta1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1" + octavia_operatorapiv1beta1 "github.com/openstack-k8s-operators/octavia-operator/api/v1beta1" ovn_operatorapiv1beta1 "github.com/openstack-k8s-operators/ovn-operator/api/v1beta1" + placement_operatorapiv1beta1 "github.com/openstack-k8s-operators/placement-operator/api/v1beta1" + swift_operatorapiv1beta1 "github.com/openstack-k8s-operators/swift-operator/api/v1beta1" + telemetry_operatorapiv1beta1 "github.com/openstack-k8s-operators/telemetry-operator/api/v1beta1" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -35,7 +51,11 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BarbicanSection) DeepCopyInto(out *BarbicanSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(barbican_operatorapiv1beta1.BarbicanSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -124,7 +144,11 @@ func (in *CertSection) DeepCopy() *CertSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderSection) DeepCopyInto(out *CinderSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(cinder_operatorapiv1beta1.CinderSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -659,7 +683,11 @@ func (in *CustomContainerImages) DeepCopy() *CustomContainerImages { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DNSMasqSection) DeepCopyInto(out *DNSMasqSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(networkv1beta1.DNSMasqSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSMasqSection. @@ -675,7 +703,11 @@ func (in *DNSMasqSection) DeepCopy() *DNSMasqSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DesignateSection) DeepCopyInto(out *DesignateSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(designate_operatorapiv1beta1.DesignateSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -694,9 +726,13 @@ func (in *GaleraSection) DeepCopyInto(out *GaleraSection) { *out = *in if in.Templates != nil { in, out := &in.Templates, &out.Templates - *out = make(map[string]apiv1beta1.GaleraSpecCore, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() + *out = new(map[string]mariadb_operatorapiv1beta1.GaleraSpecCore) + if **in != nil { + in, out := *in, *out + *out = make(map[string]mariadb_operatorapiv1beta1.GaleraSpecCore, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } } } } @@ -714,7 +750,11 @@ func (in *GaleraSection) DeepCopy() *GaleraSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GlanceSection) DeepCopyInto(out *GlanceSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(glance_operatorapiv1beta1.GlanceSpecCore) + (*in).DeepCopyInto(*out) + } if in.APIOverride != nil { in, out := &in.APIOverride, &out.APIOverride *out = make(map[string]Override, len(*in)) @@ -737,7 +777,11 @@ func (in *GlanceSection) DeepCopy() *GlanceSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HeatSection) DeepCopyInto(out *HeatSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(heat_operatorapiv1beta1.HeatSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) in.CnfAPIOverride.DeepCopyInto(&out.CnfAPIOverride) } @@ -755,7 +799,11 @@ func (in *HeatSection) DeepCopy() *HeatSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HorizonSection) DeepCopyInto(out *HorizonSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(horizon_operatorapiv1beta1.HorizonSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -772,7 +820,11 @@ func (in *HorizonSection) DeepCopy() *HorizonSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IronicSection) DeepCopyInto(out *IronicSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(ironic_operatorapiv1beta1.IronicSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) in.InspectorOverride.DeepCopyInto(&out.InspectorOverride) } @@ -790,7 +842,11 @@ func (in *IronicSection) DeepCopy() *IronicSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KeystoneSection) DeepCopyInto(out *KeystoneSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(apiv1beta1.KeystoneAPISpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -807,7 +863,11 @@ func (in *KeystoneSection) DeepCopy() *KeystoneSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManilaSection) DeepCopyInto(out *ManilaSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(manila_operatorapiv1beta1.ManilaSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -826,9 +886,13 @@ func (in *MemcachedSection) DeepCopyInto(out *MemcachedSection) { *out = *in if in.Templates != nil { in, out := &in.Templates, &out.Templates - *out = make(map[string]memcachedv1beta1.MemcachedSpecCore, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() + *out = new(map[string]memcachedv1beta1.MemcachedSpecCore) + if **in != nil { + in, out := *in, *out + *out = make(map[string]memcachedv1beta1.MemcachedSpecCore, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } } } } @@ -846,7 +910,11 @@ func (in *MemcachedSection) DeepCopy() *MemcachedSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NeutronSection) DeepCopyInto(out *NeutronSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(neutron_operatorapiv1beta1.NeutronAPISpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -879,7 +947,11 @@ func (in *NovaCellOverrideSpec) DeepCopy() *NovaCellOverrideSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NovaSection) DeepCopyInto(out *NovaSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(nova_operatorapiv1beta1.NovaSpec) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) if in.CellOverride != nil { in, out := &in.CellOverride, &out.CellOverride @@ -903,7 +975,11 @@ func (in *NovaSection) DeepCopy() *NovaSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OctaviaSection) DeepCopyInto(out *OctaviaSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(octavia_operatorapiv1beta1.OctaviaSpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -1304,7 +1380,11 @@ func (in *OvnResources) DeepCopy() *OvnResources { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OvnSection) DeepCopyInto(out *OvnSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(OvnResources) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OvnSection. @@ -1320,7 +1400,11 @@ func (in *OvnSection) DeepCopy() *OvnSection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PlacementSection) DeepCopyInto(out *PlacementSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(placement_operatorapiv1beta1.PlacementAPISpecCore) + (*in).DeepCopyInto(*out) + } in.APIOverride.DeepCopyInto(&out.APIOverride) } @@ -1339,9 +1423,13 @@ func (in *RabbitmqSection) DeepCopyInto(out *RabbitmqSection) { *out = *in if in.Templates != nil { in, out := &in.Templates, &out.Templates - *out = make(map[string]RabbitmqTemplate, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() + *out = new(map[string]RabbitmqTemplate) + if **in != nil { + in, out := *in, *out + *out = make(map[string]RabbitmqTemplate, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } } } } @@ -1375,7 +1463,11 @@ func (in *RabbitmqTemplate) DeepCopy() *RabbitmqTemplate { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SwiftSection) DeepCopyInto(out *SwiftSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(swift_operatorapiv1beta1.SwiftSpecCore) + (*in).DeepCopyInto(*out) + } in.ProxyOverride.DeepCopyInto(&out.ProxyOverride) } @@ -1495,7 +1587,11 @@ func (in *TLSStatus) DeepCopy() *TLSStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TelemetrySection) DeepCopyInto(out *TelemetrySection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(telemetry_operatorapiv1beta1.TelemetrySpecCore) + (*in).DeepCopyInto(*out) + } in.AodhAPIOverride.DeepCopyInto(&out.AodhAPIOverride) in.PrometheusOverride.DeepCopyInto(&out.PrometheusOverride) in.AlertmanagerOverride.DeepCopyInto(&out.AlertmanagerOverride) diff --git a/apis/go.mod b/apis/go.mod index 0da711217..ca6403d7d 100644 --- a/apis/go.mod +++ b/apis/go.mod @@ -38,6 +38,8 @@ require ( sigs.k8s.io/controller-runtime v0.16.6 ) +require k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 + require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -92,7 +94,6 @@ require ( k8s.io/component-base v0.28.10 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml index 147ce3cd1..af31d6307 100644 --- a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -27,6 +27,9 @@ spec: kind: OpenStackControlPlane name: openstackcontrolplanes.core.openstack.org specDescriptors: + - description: Barbican - Parameters related to the Barbican service + displayName: Barbican + path: barbican - description: APIOverride, provides the ability to override the generated manifest of several child resources. displayName: APIOverride @@ -60,6 +63,9 @@ spec: - description: Template - Overrides to use when creating Cinder Resources displayName: Template path: cinder.template + - description: Designate - Parameters related to the Designate service + displayName: Designate + path: designate - description: APIOverride, provides the ability to override the generated manifest of several child resources. displayName: APIOverride @@ -157,6 +163,9 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: horizon.apiOverride.tls + - description: Template - Overrides to use when creating the Horizon services + displayName: Template + path: horizon.template - description: Ironic - Parameters related to the Ironic services displayName: Ironic path: ironic @@ -200,6 +209,9 @@ spec: - description: Template - Overrides to use when creating the Keystone service displayName: Template path: keystone.template + - description: Manila - Parameters related to the Manila service + displayName: Manila + path: manila - description: APIOverride, provides the ability to override the generated manifest of several child resources. displayName: APIOverride @@ -212,6 +224,9 @@ spec: path: manila.enabled x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Template - Overrides to use when creating Manila Resources + displayName: Template + path: manila.template - description: Memcached - Parameters related to the Memcached service displayName: Memcached path: memcached @@ -272,6 +287,9 @@ spec: - description: Template - Overrides to use when creating the Nova services displayName: Template path: nova.template + - description: Octavia - Parameters related to the Octavia service + displayName: Octavia + path: octavia - description: APIOverride, provides the ability to override the generated manifest of several child resources. displayName: APIOverride @@ -356,6 +374,9 @@ spec: path: storageClass x-descriptors: - urn:alm:descriptor:io.kubernetes:StorageClass + - description: Swift - Parameters related to the Swift service + displayName: Swift + path: swift - description: Enabled - Whether Swift service should be deployed and managed displayName: Enabled path: swift.enabled @@ -371,6 +392,9 @@ spec: - description: Template - Overrides to use when creating Swift Resources displayName: Template path: swift.template + - description: Telemetry - Parameters related to the OpenStack Telemetry services + displayName: Telemetry + path: telemetry - description: AlertmanagerOverride, provides the ability to override the generated manifest of several child resources. displayName: Alertmanager Override diff --git a/pkg/openstack/barbican.go b/pkg/openstack/barbican.go index 5687d63f4..5544386c3 100644 --- a/pkg/openstack/barbican.go +++ b/pkg/openstack/barbican.go @@ -39,6 +39,10 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr return ctrl.Result{}, nil } + if instance.Spec.Barbican.Template == nil { + instance.Spec.Barbican.Template = &barbicanv1.BarbicanSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Barbican.Template.BarbicanAPI.Override.Service == nil { diff --git a/pkg/openstack/cinder.go b/pkg/openstack/cinder.go index 715f20420..a7825f41c 100644 --- a/pkg/openstack/cinder.go +++ b/pkg/openstack/cinder.go @@ -42,6 +42,10 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl } Log := GetLogger(ctx) + if instance.Spec.Cinder.Template == nil { + instance.Spec.Cinder.Template = &cinderv1.CinderSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Cinder.Template.CinderAPI.Override.Service == nil { diff --git a/pkg/openstack/designate.go b/pkg/openstack/designate.go index 6437ce013..5fe3174af 100644 --- a/pkg/openstack/designate.go +++ b/pkg/openstack/designate.go @@ -44,6 +44,10 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont return ctrl.Result{}, nil } + if instance.Spec.Designate.Template == nil { + instance.Spec.Designate.Template = &designatev1.DesignateSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Designate.Template.DesignateAPI.Override.Service == nil { diff --git a/pkg/openstack/dnsmasq.go b/pkg/openstack/dnsmasq.go index 5599f16a7..ecdac7395 100644 --- a/pkg/openstack/dnsmasq.go +++ b/pkg/openstack/dnsmasq.go @@ -36,6 +36,10 @@ func ReconcileDNSMasqs(ctx context.Context, instance *corev1beta1.OpenStackContr Log := GetLogger(ctx) + if instance.Spec.DNS.Template == nil { + instance.Spec.DNS.Template = &networkv1.DNSMasqSpec{} + } + Log.Info("Reconciling DNSMasq", "DNSMasq.Namespace", instance.Namespace, "DNSMasq.Name", "dnsmasq") op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), dnsmasq, func() error { instance.Spec.DNS.Template.DeepCopyInto(&dnsmasq.Spec) diff --git a/pkg/openstack/galera.go b/pkg/openstack/galera.go index bdf877d5c..d70aa275e 100644 --- a/pkg/openstack/galera.go +++ b/pkg/openstack/galera.go @@ -42,7 +42,11 @@ func ReconcileGaleras( var failures = []string{} var inprogress = []string{} - for name, spec := range instance.Spec.Galera.Templates { + if instance.Spec.Galera.Templates == nil { + instance.Spec.Galera.Templates = ptr.To(map[string]mariadbv1.GaleraSpecCore{}) + } + + for name, spec := range *instance.Spec.Galera.Templates { hostname := fmt.Sprintf("%s.%s.svc", name, instance.Namespace) hostnameHeadless := fmt.Sprintf("%s-galera.%s.svc", name, instance.Namespace) @@ -65,7 +69,7 @@ func ReconcileGaleras( // at the initial deployment because there is no SST involved when the DB is bootstrapped // as there are no data to be transferred yet. Subject: &certmgrv1.X509Subject{ - Organizations: []string{fmt.Sprintf("%s.cluster.local", instance.Namespace)}, + Organizations: []string{fmt.Sprintf("%s.%s", instance.Namespace, ClusterInternalDomain)}, }, Usages: []certmgrv1.KeyUsage{ "key encipherment", diff --git a/pkg/openstack/glance.go b/pkg/openstack/glance.go index 7af381ec8..e30f66ad5 100644 --- a/pkg/openstack/glance.go +++ b/pkg/openstack/glance.go @@ -47,6 +47,10 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl return ctrl.Result{}, nil } + if instance.Spec.Glance.Template == nil { + instance.Spec.Glance.Template = &glancev1.GlanceSpecCore{} + } + // When component services got created check if there is the need to create a route if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: "glance", Namespace: instance.Namespace}, glance); err != nil { if !k8s_errors.IsNotFound(err) { diff --git a/pkg/openstack/heat.go b/pkg/openstack/heat.go index c7b63bcca..57f070d20 100644 --- a/pkg/openstack/heat.go +++ b/pkg/openstack/heat.go @@ -43,6 +43,10 @@ func ReconcileHeat(ctx context.Context, instance *corev1beta1.OpenStackControlPl return ctrl.Result{}, nil } + if instance.Spec.Heat.Template == nil { + instance.Spec.Heat.Template = &heatv1.HeatSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Heat.Template.HeatAPI.Override.Service == nil { diff --git a/pkg/openstack/horizon.go b/pkg/openstack/horizon.go index dceb5b871..a976666da 100644 --- a/pkg/openstack/horizon.go +++ b/pkg/openstack/horizon.go @@ -46,6 +46,10 @@ func ReconcileHorizon(ctx context.Context, instance *corev1beta1.OpenStackContro return ctrl.Result{}, nil } + if instance.Spec.Horizon.Template == nil { + instance.Spec.Horizon.Template = &horizonv1.HorizonSpecCore{} + } + // add selector to service overrides serviceOverrides := map[service.Endpoint]service.RoutedOverrideSpec{} if instance.Spec.Horizon.Template.Override.Service != nil { diff --git a/pkg/openstack/ironic.go b/pkg/openstack/ironic.go index 982af64bf..eda45035d 100644 --- a/pkg/openstack/ironic.go +++ b/pkg/openstack/ironic.go @@ -43,6 +43,10 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl return ctrl.Result{}, nil } + if instance.Spec.Ironic.Template == nil { + instance.Spec.Ironic.Template = &ironicv1.IronicSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Ironic.Template.IronicAPI.Override.Service == nil { diff --git a/pkg/openstack/keystone.go b/pkg/openstack/keystone.go index 678e61ada..b49f61f24 100644 --- a/pkg/openstack/keystone.go +++ b/pkg/openstack/keystone.go @@ -39,6 +39,10 @@ func ReconcileKeystoneAPI(ctx context.Context, instance *corev1beta1.OpenStackCo return ctrl.Result{}, nil } + if instance.Spec.Keystone.Template == nil { + instance.Spec.Keystone.Template = &keystonev1.KeystoneAPISpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Keystone.Template.Override.Service == nil { diff --git a/pkg/openstack/manila.go b/pkg/openstack/manila.go index 023333dfe..8d7e85974 100644 --- a/pkg/openstack/manila.go +++ b/pkg/openstack/manila.go @@ -41,6 +41,10 @@ func ReconcileManila(ctx context.Context, instance *corev1beta1.OpenStackControl return ctrl.Result{}, nil } + if instance.Spec.Manila.Template == nil { + instance.Spec.Manila.Template = &manilav1.ManilaSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Manila.Template.ManilaAPI.Override.Service == nil { diff --git a/pkg/openstack/memcached.go b/pkg/openstack/memcached.go index 6596e65a4..463481eee 100644 --- a/pkg/openstack/memcached.go +++ b/pkg/openstack/memcached.go @@ -54,6 +54,10 @@ func ReconcileMemcacheds( return ctrl.Result{}, err } + if instance.Spec.Memcached.Templates == nil { + instance.Spec.Memcached.Templates = ptr.To(map[string]memcachedv1.MemcachedSpecCore{}) + } + for _, memcached := range memcacheds.Items { for _, ref := range memcached.GetOwnerReferences() { // Check owner UID to ensure the memcached instance is owned by this OpenStackControlPlane instance @@ -61,7 +65,7 @@ func ReconcileMemcacheds( owned := false // Check whether the name appears in spec - for name := range instance.Spec.Memcached.Templates { + for name := range *instance.Spec.Memcached.Templates { if name == memcached.GetName() { owned = true break @@ -89,7 +93,7 @@ func ReconcileMemcacheds( var ctrlResult ctrl.Result var err error var status memcachedStatus - for name, spec := range instance.Spec.Memcached.Templates { + for name, spec := range *instance.Spec.Memcached.Templates { status, ctrlResult, err = reconcileMemcached(ctx, instance, version, helper, name, &spec) switch status { diff --git a/pkg/openstack/neutron.go b/pkg/openstack/neutron.go index 5e3aee831..a575be87c 100644 --- a/pkg/openstack/neutron.go +++ b/pkg/openstack/neutron.go @@ -41,6 +41,10 @@ func ReconcileNeutron(ctx context.Context, instance *corev1beta1.OpenStackContro return ctrl.Result{}, nil } + if instance.Spec.Neutron.Template == nil { + instance.Spec.Neutron.Template = &neutronv1.NeutronAPISpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Neutron.Template.Override.Service == nil { diff --git a/pkg/openstack/nova.go b/pkg/openstack/nova.go index 4d70b9e96..ca2e561e7 100644 --- a/pkg/openstack/nova.go +++ b/pkg/openstack/nova.go @@ -63,6 +63,10 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl return ctrl.Result{}, nil } + if instance.Spec.Nova.Template == nil { + instance.Spec.Nova.Template = &novav1.NovaSpec{} + } + // When component services got created check if there is the need to create routes and certificates if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: "nova", Namespace: instance.Namespace}, nova); err != nil { if !k8s_errors.IsNotFound(err) { diff --git a/pkg/openstack/octavia.go b/pkg/openstack/octavia.go index 4785404ee..307c2f97e 100644 --- a/pkg/openstack/octavia.go +++ b/pkg/openstack/octavia.go @@ -61,6 +61,10 @@ func ReconcileOctavia(ctx context.Context, instance *corev1beta1.OpenStackContro return ctrl.Result{}, nil } + if instance.Spec.Octavia.Template == nil { + instance.Spec.Octavia.Template = &octaviav1.OctaviaSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Octavia.Template.OctaviaAPI.Override.Service == nil { diff --git a/pkg/openstack/openstackclient.go b/pkg/openstack/openstackclient.go index 4514f7a27..7e04b457a 100644 --- a/pkg/openstack/openstackclient.go +++ b/pkg/openstack/openstackclient.go @@ -43,6 +43,10 @@ func ReconcileOpenStackClient(ctx context.Context, instance *corev1.OpenStackCon } Log := GetLogger(ctx) + if !instance.Spec.Keystone.Enabled { + return ctrl.Result{}, nil + } + Log.Info("Reconciling OpenStackClient", "OpenStackClient.Namespace", instance.Namespace, "OpenStackClient.Name", openstackclient.Name) op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), openstackclient, func() error { instance.Spec.OpenStackClient.Template.DeepCopyInto(&openstackclient.Spec.OpenStackClientSpecCore) diff --git a/pkg/openstack/ovn.go b/pkg/openstack/ovn.go index 0d279895a..eac2c777b 100644 --- a/pkg/openstack/ovn.go +++ b/pkg/openstack/ovn.go @@ -31,6 +31,10 @@ func ReconcileOVN(ctx context.Context, instance *corev1beta1.OpenStackControlPla err.Error())) } + if instance.Spec.Ovn.Template == nil { + instance.Spec.Ovn.Template = &corev1beta1.OvnResources{} + } + OVNDBClustersReady, err := ReconcileOVNDbClusters(ctx, instance, version, helper) if err != nil { Log.Error(err, "Failed to reconcile OVNDBClusters") diff --git a/pkg/openstack/placement.go b/pkg/openstack/placement.go index 2763dbdb9..348ee6b4a 100644 --- a/pkg/openstack/placement.go +++ b/pkg/openstack/placement.go @@ -37,6 +37,10 @@ func ReconcilePlacementAPI(ctx context.Context, instance *corev1beta1.OpenStackC return ctrl.Result{}, nil } + if instance.Spec.Placement.Template == nil { + instance.Spec.Placement.Template = &placementv1.PlacementAPISpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Placement.Template.Override.Service == nil { diff --git a/pkg/openstack/rabbitmq.go b/pkg/openstack/rabbitmq.go index 37c78d9c5..e871d5e46 100644 --- a/pkg/openstack/rabbitmq.go +++ b/pkg/openstack/rabbitmq.go @@ -22,6 +22,7 @@ import ( corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -48,7 +49,11 @@ func ReconcileRabbitMQs( var err error var status mqStatus - for name, spec := range instance.Spec.Rabbitmq.Templates { + if instance.Spec.Rabbitmq.Templates == nil { + instance.Spec.Rabbitmq.Templates = ptr.To(map[string]corev1beta1.RabbitmqTemplate{}) + } + + for name, spec := range *instance.Spec.Rabbitmq.Templates { status, ctrlResult, err = reconcileRabbitMQ(ctx, instance, version, helper, name, spec) switch status { diff --git a/pkg/openstack/swift.go b/pkg/openstack/swift.go index 6891bc0d9..89f6ded2a 100644 --- a/pkg/openstack/swift.go +++ b/pkg/openstack/swift.go @@ -42,6 +42,10 @@ func ReconcileSwift(ctx context.Context, instance *corev1beta1.OpenStackControlP return ctrl.Result{}, nil } + if instance.Spec.Swift.Template == nil { + instance.Spec.Swift.Template = &swiftv1.SwiftSpecCore{} + } + // add selector to service overrides for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { if instance.Spec.Swift.Template.SwiftProxy.Override.Service == nil { diff --git a/pkg/openstack/telemetry.go b/pkg/openstack/telemetry.go index 97f1c7cfb..67286cfc1 100644 --- a/pkg/openstack/telemetry.go +++ b/pkg/openstack/telemetry.go @@ -53,6 +53,10 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont return ctrl.Result{}, nil } + if instance.Spec.Telemetry.Template == nil { + instance.Spec.Telemetry.Template = &telemetryv1.TelemetrySpecCore{} + } + if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: "telemetry", Namespace: instance.Namespace}, telemetry); err != nil { if !k8s_errors.IsNotFound(err) { return ctrl.Result{}, err diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index 214091541..eadb85e04 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -66,6 +66,7 @@ type Names struct { OVNControllerCertName types.NamespacedName OVNDbServerNBName types.NamespacedName OVNDbServerSBName types.NamespacedName + NeutronOVNCertName types.NamespacedName } func CreateNames(openstackControlplaneName types.NamespacedName) Names { @@ -189,6 +190,10 @@ func CreateNames(openstackControlplaneName types.NamespacedName) Names { Namespace: openstackControlplaneName.Namespace, Name: "cert-ovncontroller-ovndbs", }, + NeutronOVNCertName: types.NamespacedName{ + Namespace: openstackControlplaneName.Namespace, + Name: "cert-neutron-ovndbs", + }, } } @@ -372,19 +377,19 @@ func GetDefaultOpenStackControlPlaneSpec() map[string]interface{} { "enabled": false, }, "glance": map[string]interface{}{ - "enabled": false, + "enabled": true, }, "horizon": map[string]interface{}{ "enabled": true, }, "cinder": map[string]interface{}{ - "enabled": false, + "enabled": true, }, "ovn": map[string]interface{}{ "enabled": false, }, "neutron": map[string]interface{}{ - "enabled": false, + "enabled": true, }, "swift": map[string]interface{}{ "enabled": false, @@ -402,6 +407,12 @@ func GetDefaultOpenStackControlPlaneSpec() map[string]interface{} { "barbican": map[string]interface{}{ "enabled": false, }, + "openstackclient": map[string]interface{}{ + "enabled": true, + }, + "manila": map[string]interface{}{ + "enabled": true, + }, } } diff --git a/tests/functional/openstackoperator_controller_test.go b/tests/functional/openstackoperator_controller_test.go index 7ab136275..3f05a06d1 100644 --- a/tests/functional/openstackoperator_controller_test.go +++ b/tests/functional/openstackoperator_controller_test.go @@ -557,13 +557,18 @@ var _ = Describe("OpenStackOperator controller", func() { // Default route timeouts are set It("should have default timeout for the routes set", func() { OSCtlplane := GetOpenStackControlPlane(names.OpenStackControlplaneName) + Expect(OSCtlplane).Should(Not(BeNil())) + Expect(OSCtlplane.Spec.Neutron.APIOverride.Route).Should(Not(BeNil())) Expect(OSCtlplane.Spec.Neutron.APIOverride.Route.Annotations).Should(HaveKeyWithValue("haproxy.router.openshift.io/timeout", "120s")) + Expect(OSCtlplane.Spec.Cinder.APIOverride.Route).Should(Not(BeNil())) Expect(OSCtlplane.Spec.Cinder.APIOverride.Route.Annotations).Should(HaveKeyWithValue("haproxy.router.openshift.io/timeout", "60s")) Expect(OSCtlplane.Spec.Cinder.APIOverride.Route.Annotations).Should(HaveKeyWithValue("api.cinder.openstack.org/timeout", "60s")) + Expect(OSCtlplane.Spec.Glance.Template).Should(Not(BeNil())) for name := range OSCtlplane.Spec.Glance.Template.GlanceAPIs { Expect(OSCtlplane.Spec.Glance.APIOverride[name].Route.Annotations).Should(HaveKeyWithValue("haproxy.router.openshift.io/timeout", "60s")) Expect(OSCtlplane.Spec.Glance.APIOverride[name].Route.Annotations).Should(HaveKeyWithValue("api.glance.openstack.org/timeout", "60s")) } + Expect(OSCtlplane.Spec.Manila.APIOverride.Route).Should(Not(BeNil())) Expect(OSCtlplane.Spec.Manila.APIOverride.Route.Annotations).Should(HaveKeyWithValue("haproxy.router.openshift.io/timeout", "60s")) Expect(OSCtlplane.Spec.Manila.APIOverride.Route.Annotations).Should(HaveKeyWithValue("api.manila.openstack.org/timeout", "60s")) }) @@ -727,6 +732,7 @@ var _ = Describe("OpenStackOperator controller", func() { // create cert secrets for ovn instance DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNNorthdCertName)) DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNControllerCertName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.NeutronOVNCertName)) DeferCleanup( th.DeleteInstance, CreateOpenStackControlPlane(names.OpenStackControlplaneName, GetDefaultOpenStackControlPlaneSpec()), @@ -770,6 +776,8 @@ var _ = Describe("OpenStackOperator controller", func() { // Default route timeouts are set It("should have default timeout for the routes set", func() { OSCtlplane := GetOpenStackControlPlane(names.OpenStackControlplaneName) + Expect(OSCtlplane).Should(Not(BeNil())) + Expect(OSCtlplane.Spec.Neutron.APIOverride.Route).Should(Not(BeNil())) Expect(OSCtlplane.Spec.Neutron.APIOverride.Route.Annotations).Should(HaveKeyWithValue("haproxy.router.openshift.io/timeout", "120s")) }) @@ -1015,6 +1023,7 @@ var _ = Describe("OpenStackOperator controller", func() { // create cert secrets for ovn instance DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNNorthdCertName)) DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNControllerCertName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.NeutronOVNCertName)) spec := GetDefaultOpenStackControlPlaneSpec() spec["tls"] = GetTLSeCustomIssuerSpec() DeferCleanup( @@ -1141,6 +1150,7 @@ var _ = Describe("OpenStackOperator controller", func() { // create cert secrets for ovn instance DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNNorthdCertName)) DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.OVNControllerCertName)) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.NeutronOVNCertName)) DeferCleanup(k8sClient.Delete, ctx, th.CreateSecret(types.NamespacedName{Name: "openstack-config-secret", Namespace: namespace}, map[string][]byte{"secure.yaml": []byte("foo")}))