diff --git a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml index 22446ecdb..6f867b75b 100644 --- a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -15770,6 +15770,28 @@ spec: type: object type: object type: object + redis: + properties: + enabled: + default: false + type: boolean + templates: + additionalProperties: + properties: + replicas: + default: 1 + format: int32 + type: integer + tls: + properties: + caBundleSecretName: + type: string + secretName: + type: string + type: object + type: object + type: object + type: object secret: type: string storageClass: @@ -17591,6 +17613,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: diff --git a/apis/bases/core.openstack.org_openstackversions.yaml b/apis/bases/core.openstack.org_openstackversions.yaml index 68a5c3c2a..48bf17ccc 100644 --- a/apis/bases/core.openstack.org_openstackversions.yaml +++ b/apis/bases/core.openstack.org_openstackversions.yaml @@ -127,6 +127,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: @@ -328,6 +330,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: @@ -500,6 +504,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: diff --git a/apis/core/v1beta1/conditions.go b/apis/core/v1beta1/conditions.go index 5290ad793..c04b362dc 100644 --- a/apis/core/v1beta1/conditions.go +++ b/apis/core/v1beta1/conditions.go @@ -132,6 +132,9 @@ const ( // OpenStackControlPlaneBarbicanReadyCondition Status=True condition which indicates if Barbican is configured and operational OpenStackControlPlaneBarbicanReadyCondition condition.Type = "OpenStackControlPlaneBarbicanReady" + // OpenStackControlPlaneRedisReadyCondition Status=True condition which indicates if Redis is configured and operational + OpenStackControlPlaneRedisReadyCondition condition.Type = "OpenStackControlPlaneRedisReady" + // OpenStackControlPlaneExposeOctaviaReadyCondition Status=True condition which indicates if Octavia is exposed via a route OpenStackControlPlaneExposeOctaviaReadyCondition condition.Type = "OpenStackControlPlaneExposeOctaviaReady" @@ -406,6 +409,18 @@ const ( // OpenStackControlPlaneManilaReadyErrorMessage OpenStackControlPlaneManilaReadyErrorMessage = "OpenStackControlPlane Manila error occured %s" + // OpenStackControlPlaneRedisReadyInitMessage + OpenStackControlPlaneRedisReadyInitMessage = "OpenStackControlPlane Redis not started" + + // OpenStackControlPlaneRedisReadyMessage + OpenStackControlPlaneRedisReadyMessage = "OpenStackControlPlane Redis completed" + + // OpenStackControlPlaneRedisReadyRunningMessage + OpenStackControlPlaneRedisReadyRunningMessage = "OpenStackControlPlane Redis in progress" + + // OpenStackControlPlaneRedisReadyErrorMessage + OpenStackControlPlaneRedisReadyErrorMessage = "OpenStackControlPlane Redis error occured %s" + // OpenStackControlPlaneExposeServiceReadyInitMessage OpenStackControlPlaneExposeServiceReadyInitMessage = "OpenStackControlPlane %s exposing service %s not started" diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index 2e6a9afaf..289cc7e30 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -27,6 +27,7 @@ import ( 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" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" @@ -195,6 +196,9 @@ type OpenStackControlPlaneSpec struct { // Barbican - Parameters related to the Barbican service Barbican BarbicanSection `json:"barbican,omitempty"` + // Redis - Parameters related to the Redis service + Redis RedisSection `json:"redis,omitempty"` + // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OpenStack Client" // OpenStackClient - Parameters related to the OpenStackClient @@ -780,6 +784,20 @@ type BarbicanSection struct { APIOverride Override `json:"apiOverride,omitempty"` } +// RedisSection defines the desired state of the Redis service +type RedisSection struct { + // +kubebuilder:validation:Optional + // Enabled - Whether the Redis service should be deployed and managed + // +kubebuilder:default=false + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + Enabled bool `json:"enabled"` + + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec + // Templates - Overrides to use when creating the Redis Resources + Templates *map[string]redisv1.RedisSpecCore `json:"templates,omitempty"` +} + // OpenStackClientSection defines the desired state of the OpenStackClient type OpenStackClientSection struct { // +kubebuilder:validation:Optional @@ -900,6 +918,7 @@ func (instance *OpenStackControlPlane) InitConditions() { condition.UnknownCondition(OpenStackControlPlaneOctaviaReadyCondition, condition.InitReason, OpenStackControlPlaneOctaviaReadyInitMessage), condition.UnknownCondition(OpenStackControlPlaneDesignateReadyCondition, condition.InitReason, OpenStackControlPlaneDesignateReadyInitMessage), condition.UnknownCondition(OpenStackControlPlaneBarbicanReadyCondition, condition.InitReason, OpenStackControlPlaneBarbicanReadyInitMessage), + condition.UnknownCondition(OpenStackControlPlaneRedisReadyCondition, condition.InitReason, OpenStackControlPlaneRedisReadyInitMessage), condition.UnknownCondition(OpenStackControlPlaneCAReadyCondition, condition.InitReason, OpenStackControlPlaneCAReadyInitMessage), // Also add the overall status condition as Unknown diff --git a/apis/core/v1beta1/openstackcontrolplane_webhook.go b/apis/core/v1beta1/openstackcontrolplane_webhook.go index 646251a5a..2f6d35617 100644 --- a/apis/core/v1beta1/openstackcontrolplane_webhook.go +++ b/apis/core/v1beta1/openstackcontrolplane_webhook.go @@ -46,6 +46,7 @@ import ( 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" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/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" @@ -223,6 +224,7 @@ func (r *OpenStackControlPlane) checkDepsEnabled(name string) string { reqs = "Galera, Keystone" } case "Octavia": + // TODO(beagles): So far we haven't declared Redis as dependency for Octavia, but we might. if !((r.Spec.Galera.Enabled) && r.Spec.Memcached.Enabled && r.Spec.Rabbitmq.Enabled && r.Spec.Keystone.Enabled && r.Spec.Neutron.Enabled && r.Spec.Glance.Enabled && r.Spec.Nova.Enabled && r.Spec.Ovn.Enabled) { @@ -338,6 +340,16 @@ func (r *OpenStackControlPlane) ValidateCreateServices(basePath *field.Path) (ad } } + if r.Spec.Redis.Enabled { + if r.Spec.Redis.Templates != nil { + err := common_webhook.ValidateDNS1123Label( + basePath.Child("redis").Child("templates"), + maps.Keys(*r.Spec.Redis.Templates), + redisv1.CrMaxLengthCorrection) // omit issue with statefulset pod label "controller-revision-hash": "-" + errors = append(errors, err...) + } + } + if r.Spec.Rabbitmq.Enabled { if r.Spec.Rabbitmq.Templates != nil { err := common_webhook.ValidateDNS1123Label( @@ -874,6 +886,20 @@ func (r *OpenStackControlPlane) DefaultServices() { } r.Spec.Designate.Template.Default() } + + // Redis + if r.Spec.Redis.Enabled || r.Spec.Redis.Templates != nil { + if r.Spec.Redis.Templates == nil { + r.Spec.Redis.Templates = ptr.To(map[string]redisv1.RedisSpecCore{}) + } + + for key, template := range *r.Spec.Redis.Templates { + template.Default() + // By-value copy, need to update + (*r.Spec.Redis.Templates)[key] = template + } + } + } // DefaultLabel - adding default label to the OpenStackControlPlane diff --git a/apis/core/v1beta1/openstackversion_types.go b/apis/core/v1beta1/openstackversion_types.go index 0bfcfd4ba..b13c809a3 100644 --- a/apis/core/v1beta1/openstackversion_types.go +++ b/apis/core/v1beta1/openstackversion_types.go @@ -113,6 +113,7 @@ type ContainerTemplate struct { HorizonImage *string `json:"horizonImage,omitempty"` InfraDnsmasqImage *string `json:"infraDnsmasqImage,omitempty"` InfraMemcachedImage *string `json:"infraMemcachedImage,omitempty"` + InfraRedisImage *string `json:"infraRedisImage,omitempty"` IronicAPIImage *string `json:"ironicAPIImage,omitempty"` IronicConductorImage *string `json:"ironicConductorImage,omitempty"` IronicInspectorImage *string `json:"ironicInspectorImage,omitempty"` diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index 893942acc..2269aff10 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -30,6 +30,7 @@ import ( 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" + redisv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/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" @@ -457,6 +458,11 @@ func (in *ContainerTemplate) DeepCopyInto(out *ContainerTemplate) { *out = new(string) **out = **in } + if in.InfraRedisImage != nil { + in, out := &in.InfraRedisImage, &out.InfraRedisImage + *out = new(string) + **out = **in + } if in.IronicAPIImage != nil { in, out := &in.IronicAPIImage, &out.IronicAPIImage *out = new(string) @@ -1139,6 +1145,7 @@ func (in *OpenStackControlPlaneSpec) DeepCopyInto(out *OpenStackControlPlaneSpec in.Octavia.DeepCopyInto(&out.Octavia) in.Designate.DeepCopyInto(&out.Designate) in.Barbican.DeepCopyInto(&out.Barbican) + in.Redis.DeepCopyInto(&out.Redis) in.OpenStackClient.DeepCopyInto(&out.OpenStackClient) if in.ExtraMounts != nil { in, out := &in.ExtraMounts, &out.ExtraMounts @@ -1485,6 +1492,32 @@ func (in *RabbitmqTemplate) DeepCopy() *RabbitmqTemplate { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisSection) DeepCopyInto(out *RedisSection) { + *out = *in + if in.Templates != nil { + in, out := &in.Templates, &out.Templates + *out = new(map[string]redisv1beta1.RedisSpecCore) + if **in != nil { + in, out := *in, *out + *out = make(map[string]redisv1beta1.RedisSpecCore, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSection. +func (in *RedisSection) DeepCopy() *RedisSection { + if in == nil { + return nil + } + out := new(RedisSection) + in.DeepCopyInto(out) + return out +} + // 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 diff --git a/apis/go.mod b/apis/go.mod index 9482326fc..85c5e49d4 100644 --- a/apis/go.mod +++ b/apis/go.mod @@ -13,7 +13,7 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.4.1-0.20240908131444-6faca68a0085 github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5cc7eedbbbe github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b - github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c + github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219 github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726 github.com/openstack-k8s-operators/keystone-operator/api v0.4.1-0.20240906103150-990fe66f2e5d github.com/openstack-k8s-operators/lib-common/modules/common v0.4.1-0.20240905123813-174296c09ec6 diff --git a/apis/go.sum b/apis/go.sum index f469adfc8..b2de80740 100644 --- a/apis/go.sum +++ b/apis/go.sum @@ -102,8 +102,8 @@ github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5c github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5cc7eedbbbe/go.mod h1:w+8OpHuUfk4nEUSQfFZbYGPZEkn0c1xe3fyZ062fkDA= github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b h1:B4kw/FovC+mKMRA8dahi2k3x751iOuBwglu9DBz0iX4= github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b/go.mod h1:Q9/AUCUCA959gIq3DxzUdTWvkwqDp0lz3ujW0vTPdWg= -github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c h1:MzX8sckaTW4eIvr5KP5XZnkFJGHy4LpsT6vsDBKBti4= -github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c/go.mod h1:TFh01OyR/NP5Sy7vikMIpQc80AKl0WWPyYDaJBfFiGc= +github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219 h1:o0epGu5XkImn5pggs/eyZMBS2Iok8wSaaTXRBwybDCk= +github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219/go.mod h1:TFh01OyR/NP5Sy7vikMIpQc80AKl0WWPyYDaJBfFiGc= github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726 h1:p82H6uTy42vBUQTrtjZovrqPNl9dEP+zEHDHpLjPKD4= github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726/go.mod h1:33VtB5iMt9SGJafuB3VCEgw1ezM4CBZ0xh0LU48+/ro= github.com/openstack-k8s-operators/keystone-operator/api v0.4.1-0.20240906103150-990fe66f2e5d h1:PbTZo4RCo+RFiGZ0q/rllUXoUtxgtWAh4V0IUe3aW5k= diff --git a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml index 22446ecdb..6f867b75b 100644 --- a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -15770,6 +15770,28 @@ spec: type: object type: object type: object + redis: + properties: + enabled: + default: false + type: boolean + templates: + additionalProperties: + properties: + replicas: + default: 1 + format: int32 + type: integer + tls: + properties: + caBundleSecretName: + type: string + secretName: + type: string + type: object + type: object + type: object + type: object secret: type: string storageClass: @@ -17591,6 +17613,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: diff --git a/config/crd/bases/core.openstack.org_openstackversions.yaml b/config/crd/bases/core.openstack.org_openstackversions.yaml index 68a5c3c2a..48bf17ccc 100644 --- a/config/crd/bases/core.openstack.org_openstackversions.yaml +++ b/config/crd/bases/core.openstack.org_openstackversions.yaml @@ -127,6 +127,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: @@ -328,6 +330,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: @@ -500,6 +504,8 @@ spec: type: string infraMemcachedImage: type: string + infraRedisImage: + type: string ironicAPIImage: type: string ironicConductorImage: diff --git a/config/default/manager_default_images.yaml b/config/default/manager_default_images.yaml index f70700c4b..fccaa17a0 100644 --- a/config/default/manager_default_images.yaml +++ b/config/default/manager_default_images.yaml @@ -95,6 +95,8 @@ spec: value: quay.io/podified-antelope-centos9/openstack-horizon:current-podified - name: RELATED_IMAGE_INFRA_MEMCACHED_IMAGE_URL_DEFAULT value: quay.io/podified-antelope-centos9/openstack-memcached:current-podified + - name: RELATED_IMAGE_INFRA_REDIS_IMAGE_URL_DEFAULT + value: quay.io/podified-antelope-centos9/openstack-redis:current-podified - name: RELATED_IMAGE_IRONIC_API_IMAGE_URL_DEFAULT value: quay.io/podified-antelope-centos9/openstack-ironic-api:current-podified - name: RELATED_IMAGE_IRONIC_CONDUCTOR_IMAGE_URL_DEFAULT diff --git a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml index c71671e06..39a4191d1 100644 --- a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -374,6 +374,14 @@ spec: - description: Templates - Overrides to use when creating the Rabbitmq clusters displayName: Templates path: rabbitmq.templates + - description: Enabled - Whether the Redis service should be deployed and managed + displayName: Enabled + path: redis.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Templates - Overrides to use when creating the Redis Resources + displayName: Templates + path: redis.templates - description: 'Secret - FIXME: make this optional' displayName: Secret path: secret diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index ac529c6f1..a8a75d8ae 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -735,6 +735,18 @@ rules: - patch - update - watch +- apiGroups: + - redis.openstack.org + resources: + - redises + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - route.openshift.io resources: diff --git a/config/samples/base/openstackcontrolplane/core_v1beta1_openstackcontrolplane.yaml b/config/samples/base/openstackcontrolplane/core_v1beta1_openstackcontrolplane.yaml index c242240d5..f2e59375d 100644 --- a/config/samples/base/openstackcontrolplane/core_v1beta1_openstackcontrolplane.yaml +++ b/config/samples/base/openstackcontrolplane/core_v1beta1_openstackcontrolplane.yaml @@ -179,6 +179,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: template: databaseInstance: openstack diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera.yaml index 3c803f628..2e3084cf9 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera.yaml @@ -192,6 +192,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_3replicas.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_3replicas.yaml index c3ac4f017..65b0b69be 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_3replicas.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_3replicas.yaml @@ -177,6 +177,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml index 87ee8b7c3..99616c0a5 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml @@ -379,6 +379,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml index 0a206fbf3..f12114fee 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml @@ -381,6 +381,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml index 5d7669129..67a93dcff 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml @@ -375,6 +375,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml index 44fd366dc..113207d1c 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml @@ -411,6 +411,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tls_public_endpoint.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tls_public_endpoint.yaml index a4de194af..0fbdd82ff 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tls_public_endpoint.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tls_public_endpoint.yaml @@ -378,6 +378,8 @@ spec: octaviaAPI: replicas: 1 secret: osp-secret + redis: + enabled: false designate: enabled: false apiOverride: diff --git a/controllers/core/openstackcontrolplane_controller.go b/controllers/core/openstackcontrolplane_controller.go index a445f5471..9a1a2e590 100644 --- a/controllers/core/openstackcontrolplane_controller.go +++ b/controllers/core/openstackcontrolplane_controller.go @@ -27,6 +27,7 @@ import ( 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" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" @@ -105,6 +106,7 @@ func (r *OpenStackControlPlaneReconciler) GetLogger(ctx context.Context) logr.Lo // +kubebuilder:rbac:groups=octavia.openstack.org,resources=octavias,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=barbican.openstack.org,resources=barbicans,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=designate.openstack.org,resources=designates,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=redis.openstack.org,resources=redises,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=route.openshift.io,resources=routes/custom-host,verbs=create;update;patch // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list; @@ -415,6 +417,13 @@ func (r *OpenStackControlPlaneReconciler) reconcileNormal(ctx context.Context, i return ctrlResult, nil } + ctrlResult, err = openstack.ReconcileRedis(ctx, instance, version, helper) + if err != nil { + return ctrl.Result{}, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + ctrlResult, err = openstack.ReconcileOctavia(ctx, instance, version, helper) if err != nil { return ctrl.Result{}, err @@ -565,6 +574,7 @@ func (r *OpenStackControlPlaneReconciler) SetupWithManager( Owns(&ironicv1.Ironic{}). Owns(&horizonv1.Horizon{}). Owns(&telemetryv1.Telemetry{}). + Owns(&redisv1.Redis{}). Owns(&octaviav1.Octavia{}). Owns(&designatev1.Designate{}). Owns(&routev1.Route{}). diff --git a/go.mod b/go.mod index 7ccfa64c6..7bd39b9a5 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.4.1-0.20240908131444-6faca68a0085 github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5cc7eedbbbe github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b - github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c + github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219 github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726 github.com/openstack-k8s-operators/keystone-operator/api v0.4.1-0.20240906103150-990fe66f2e5d github.com/openstack-k8s-operators/lib-common/modules/ansible v0.4.1-0.20240905123813-174296c09ec6 diff --git a/go.sum b/go.sum index a82e59e16..2815f42c5 100644 --- a/go.sum +++ b/go.sum @@ -108,8 +108,8 @@ github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5c github.com/openstack-k8s-operators/heat-operator/api v0.4.1-0.20240907050635-d5cc7eedbbbe/go.mod h1:w+8OpHuUfk4nEUSQfFZbYGPZEkn0c1xe3fyZ062fkDA= github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b h1:B4kw/FovC+mKMRA8dahi2k3x751iOuBwglu9DBz0iX4= github.com/openstack-k8s-operators/horizon-operator/api v0.4.1-0.20240906120219-9c3e4ba4077b/go.mod h1:Q9/AUCUCA959gIq3DxzUdTWvkwqDp0lz3ujW0vTPdWg= -github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c h1:MzX8sckaTW4eIvr5KP5XZnkFJGHy4LpsT6vsDBKBti4= -github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240906153437-12ffed69a34c/go.mod h1:TFh01OyR/NP5Sy7vikMIpQc80AKl0WWPyYDaJBfFiGc= +github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219 h1:o0epGu5XkImn5pggs/eyZMBS2Iok8wSaaTXRBwybDCk= +github.com/openstack-k8s-operators/infra-operator/apis v0.4.1-0.20240910085802-31f905cfe219/go.mod h1:TFh01OyR/NP5Sy7vikMIpQc80AKl0WWPyYDaJBfFiGc= github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726 h1:p82H6uTy42vBUQTrtjZovrqPNl9dEP+zEHDHpLjPKD4= github.com/openstack-k8s-operators/ironic-operator/api v0.4.1-0.20240807084947-190400f63726/go.mod h1:33VtB5iMt9SGJafuB3VCEgw1ezM4CBZ0xh0LU48+/ro= github.com/openstack-k8s-operators/keystone-operator/api v0.4.1-0.20240906103150-990fe66f2e5d h1:PbTZo4RCo+RFiGZ0q/rllUXoUtxgtWAh4V0IUe3aW5k= diff --git a/hack/export_related_images.sh b/hack/export_related_images.sh index c9d32f2cc..d32b33b7d 100755 --- a/hack/export_related_images.sh +++ b/hack/export_related_images.sh @@ -6,6 +6,7 @@ export RELATED_IMAGE_RABBITMQ_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos export RELATED_IMAGE_KEYSTONE_API_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-keystone:current-podified export RELATED_IMAGE_MARIADB_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-mariadb:current-podified export RELATED_IMAGE_INFRA_MEMCACHED_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-memcached:current-podified +export RELATED_IMAGE_INFRA_REDIS_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-redis:current-podified export RELATED_IMAGE_ANSIBLEEE_IMAGE_URL_DEFAULT=quay.io/openstack-k8s-operators/openstack-ansibleee-runner:current-podified export RELATED_IMAGE_NOVA_API_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-nova-api:current-podified export RELATED_IMAGE_NOVA_CONDUCTOR_IMAGE_URL_DEFAULT=quay.io/podified-antelope-centos9/openstack-nova-conductor:current-podified diff --git a/main.go b/main.go index fa9996e06..fcce23ac9 100644 --- a/main.go +++ b/main.go @@ -39,6 +39,7 @@ import ( memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" networkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1" rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" manilav1 "github.com/openstack-k8s-operators/manila-operator/api/v1beta1" @@ -114,6 +115,7 @@ func init() { utilruntime.Must(telemetryv1.AddToScheme(scheme)) utilruntime.Must(swiftv1.AddToScheme(scheme)) utilruntime.Must(clientv1.AddToScheme(scheme)) + utilruntime.Must(redisv1.AddToScheme(scheme)) utilruntime.Must(routev1.AddToScheme(scheme)) utilruntime.Must(certmgrv1.AddToScheme(scheme)) utilruntime.Must(barbicanv1.AddToScheme(scheme)) diff --git a/pkg/openstack/common.go b/pkg/openstack/common.go index ec4cfb8c0..177acf076 100644 --- a/pkg/openstack/common.go +++ b/pkg/openstack/common.go @@ -14,6 +14,7 @@ import ( heatv1 "github.com/openstack-k8s-operators/heat-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" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/certmanager" @@ -709,6 +710,9 @@ func SetupServiceOperatorDefaults() { // Heat heatv1.SetupDefaults() + // Redis + redisv1.SetupDefaults() + // DNS networkv1.SetupDefaults() diff --git a/pkg/openstack/redis.go b/pkg/openstack/redis.go new file mode 100644 index 000000000..28b2881e7 --- /dev/null +++ b/pkg/openstack/redis.go @@ -0,0 +1,265 @@ +package openstack + +import ( + "context" + "fmt" + "strings" + + certmgrv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" + "github.com/openstack-k8s-operators/lib-common/modules/certmanager" + "github.com/openstack-k8s-operators/lib-common/modules/common/condition" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" + + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type redisStatus int + +const ( + redisFailed redisStatus = iota + redisCreating redisStatus = iota + redisReady redisStatus = iota +) + +// ReconcileRedis - +func ReconcileRedis( + ctx context.Context, + instance *corev1beta1.OpenStackControlPlane, + version *corev1beta1.OpenStackVersion, + helper *helper.Helper, +) (ctrl.Result, error) { + var failures = []string{} + var inprogress = []string{} + + // NOTE(beagles): This performs quite a bit of processing to purge + // even if the controller is meant to be disabled and might set an + // error condition somewhere along the way. I suspect this is + // actually desirable because it indicates that the cluster is + // somehow in a state that the operator doesn't know how to + // reconcile. The implementation will need to careful about the + // disabled from the start scenario when it likely should *not* + // start appearing in conditions. It also means that the situation + // where sample template data in a config where redis is disabled + // will require require that the controller iterator over the + // specs and make sure that existing deployed redis instances are + // deleted. Generally means if we want the redis controller to + // truly remain invisible it's best not to provide any example + // templates info while the service is disabled. + + // We first remove redises no longer owned + redises := &redisv1.RedisList{} + listOpts := []client.ListOption{ + client.InNamespace(instance.Namespace), + } + if err := helper.GetClient().List(ctx, redises, listOpts...); err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + corev1beta1.OpenStackControlPlaneRedisReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + corev1beta1.OpenStackControlPlaneRedisReadyErrorMessage, + err)) + return ctrl.Result{}, err + } + + if instance.Spec.Redis.Templates == nil { + instance.Spec.Redis.Templates = ptr.To(map[string]redisv1.RedisSpecCore{}) + } + + for _, redis := range redises.Items { + for _, ref := range redis.GetOwnerReferences() { + // Check owner UID to ensure the redis instance is owned by this OpenStackControlPlane instance + if ref.UID == instance.GetUID() { + owned := false + + // Check whether the name appears in spec + for name := range *instance.Spec.Redis.Templates { + if name == redis.GetName() { + owned = true + break + } + } + + // The instance name is no longer part of the spec. Let's delete it + if !owned { + mc := &redisv1.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: redis.GetName(), + Namespace: redis.GetNamespace(), + }, + } + _, err := EnsureDeleted(ctx, helper, mc) + if err != nil { + failures = append(failures, fmt.Sprintf("%s(deleted)(%v)", redis.GetName(), err.Error())) + } + } + } + } + } + + // then reconcile ones listed in spec + var ctrlResult ctrl.Result + var err error + var status redisStatus + + for name, spec := range *instance.Spec.Redis.Templates { + status, ctrlResult, err = reconcileRedis(ctx, instance, version, helper, name, &spec) + + switch status { + case redisFailed: + failures = append(failures, fmt.Sprintf("%s(%v)", name, err.Error())) + case redisCreating: + inprogress = append(inprogress, name) + case redisReady: + default: + failures = append(failures, fmt.Sprintf("Invalid redisStatus from reconcileRedis: %d for Redis %s", status, name)) + } + } + + if len(failures) > 0 { + errors := strings.Join(failures, ",") + + instance.Status.Conditions.Set(condition.FalseCondition( + corev1beta1.OpenStackControlPlaneRedisReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + corev1beta1.OpenStackControlPlaneRedisReadyErrorMessage, + errors)) + + return ctrlResult, fmt.Errorf(errors) + + } else if len(inprogress) > 0 { + instance.Status.Conditions.Set(condition.FalseCondition( + corev1beta1.OpenStackControlPlaneRedisReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + corev1beta1.OpenStackControlPlaneRedisReadyRunningMessage)) + } else if !instance.Spec.Redis.Enabled { + instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneRedisReadyCondition) + } else { + instance.Status.Conditions.MarkTrue( + corev1beta1.OpenStackControlPlaneRedisReadyCondition, + corev1beta1.OpenStackControlPlaneRedisReadyMessage, + ) + } + + return ctrlResult, nil +} + +// reconcileRedis - +func reconcileRedis( + ctx context.Context, + instance *corev1beta1.OpenStackControlPlane, + version *corev1beta1.OpenStackVersion, + helper *helper.Helper, + name string, + spec *redisv1.RedisSpecCore, +) (redisStatus, ctrl.Result, error) { + redis := &redisv1.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: instance.Namespace, + }, + } + + if !instance.Spec.Redis.Enabled { + if _, err := EnsureDeleted(ctx, helper, redis); err != nil { + return redisFailed, ctrl.Result{}, err + } + return redisReady, ctrl.Result{}, nil + } + + helper.GetLogger().Info("Reconciling Redis", "Redis.Namespace", instance.Namespace, "Redis.Name", name) + + tlsCert := "" + if instance.Spec.TLS.PodLevel.Enabled { + certRequest := certmanager.CertificateRequest{ + IssuerName: instance.GetInternalIssuer(), + CertName: fmt.Sprintf("%s-svc", redis.Name), + Hostnames: []string{ + fmt.Sprintf("redis-%s.%s.svc", name, instance.Namespace), + fmt.Sprintf("*.redis-%s.%s.svc", name, instance.Namespace), + fmt.Sprintf("redis-%s.%s.svc.%s", name, instance.Namespace, ClusterInternalDomain), + fmt.Sprintf("*.redis-%s.%s.svc.%s", name, instance.Namespace, ClusterInternalDomain), + }, + Subject: &certmgrv1.X509Subject{ + Organizations: []string{fmt.Sprintf("%s.%s", instance.Namespace, ClusterInternalDomain)}, + }, + Usages: []certmgrv1.KeyUsage{ + "key encipherment", + "digital signature", + "server auth", + "client auth", + }, + } + if instance.Spec.TLS.PodLevel.Internal.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.PodLevel.Internal.Cert.Duration.Duration + } + if instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore.Duration + } + certSecret, ctrlResult, err := certmanager.EnsureCert( + ctx, + helper, + certRequest, + nil) + if err != nil { + return redisFailed, ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return redisCreating, ctrlResult, nil + } + + tlsCert = certSecret.Name + } + + op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), redis, func() error { + spec.DeepCopyInto(&redis.Spec.RedisSpecCore) + if tlsCert != "" { + + redis.Spec.TLS.SecretName = ptr.To(tlsCert) + } + redis.Spec.TLS.CaBundleSecretName = tls.CABundleSecret + + redis.Spec.ContainerImage = *version.Status.ContainerImages.InfraRedisImage + err := controllerutil.SetControllerReference(helper.GetBeforeObject(), redis, helper.GetScheme()) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + return redisFailed, ctrl.Result{}, err + } + if op != controllerutil.OperationResultNone { + helper.GetLogger().Info(fmt.Sprintf("Redis %s - %s", redis.Name, op)) + } + + if redis.IsReady() { //FIXME ObserverdGeneration + instance.Status.ContainerImages.InfraRedisImage = version.Status.ContainerImages.InfraRedisImage + return redisReady, ctrl.Result{}, nil + } + + return redisCreating, ctrl.Result{}, nil +} + +// RedisImageMatch - return true if the redis images match on the ControlPlane and Version, or if Redis is not enabled +func RedisImageMatch(ctx context.Context, controlPlane *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion) bool { + Log := GetLogger(ctx) + if controlPlane.Spec.Redis.Enabled { + if !stringPointersEqual(controlPlane.Status.ContainerImages.InfraRedisImage, version.Status.ContainerImages.InfraRedisImage) { + Log.Info("Redis images do not match", "controlPlane.Status.ContainerImages.InfraRedisImage", controlPlane.Status.ContainerImages.InfraRedisImage, "version.Status.ContainerImages.InfraRedisImage", version.Status.ContainerImages.InfraRedisImage) + return false + } + } + + return true +} diff --git a/pkg/openstack/version.go b/pkg/openstack/version.go index 1ba4daed8..70de6946c 100644 --- a/pkg/openstack/version.go +++ b/pkg/openstack/version.go @@ -125,6 +125,7 @@ func GetContainerImages(defaults *corev1beta1.ContainerDefaults, instance corev1 HorizonImage: getImg(instance.Spec.CustomContainerImages.HorizonImage, defaults.HorizonImage), InfraDnsmasqImage: getImg(instance.Spec.CustomContainerImages.InfraDnsmasqImage, defaults.InfraDnsmasqImage), InfraMemcachedImage: getImg(instance.Spec.CustomContainerImages.InfraMemcachedImage, defaults.InfraMemcachedImage), + InfraRedisImage: getImg(instance.Spec.CustomContainerImages.InfraRedisImage, defaults.InfraRedisImage), IronicAPIImage: getImg(instance.Spec.CustomContainerImages.IronicAPIImage, defaults.IronicAPIImage), IronicConductorImage: getImg(instance.Spec.CustomContainerImages.IronicConductorImage, defaults.IronicConductorImage), IronicInspectorImage: getImg(instance.Spec.CustomContainerImages.IronicInspectorImage, defaults.IronicInspectorImage), @@ -265,6 +266,9 @@ func ControlplaneContainerImageMatch(ctx context.Context, controlPlane *corev1be if MemcachedImageMatch(ctx, controlPlane, version) { failedMatches = append(failedMatches, "Memcached") } + if RedisImageMatch(ctx, controlPlane, version) { + failedMatches = append(failedMatches, "Redis") + } if NeutronImageMatch(ctx, controlPlane, version) { failedMatches = append(failedMatches, "Neutron") } diff --git a/tests/functional/ctlplane/base_test.go b/tests/functional/ctlplane/base_test.go index 9027072aa..92d171881 100644 --- a/tests/functional/ctlplane/base_test.go +++ b/tests/functional/ctlplane/base_test.go @@ -453,6 +453,9 @@ func GetDefaultOpenStackControlPlaneSpec() map[string]interface{} { "nova": map[string]interface{}{ "enabled": false, }, + "redis": map[string]interface{}{ + "enabled": false, + }, "ironic": map[string]interface{}{ "enabled": false, "template": ironicTemplate, diff --git a/tests/functional/ctlplane/openstackversion_controller_test.go b/tests/functional/ctlplane/openstackversion_controller_test.go index 0e5043ab8..f5deccd39 100644 --- a/tests/functional/ctlplane/openstackversion_controller_test.go +++ b/tests/functional/ctlplane/openstackversion_controller_test.go @@ -138,6 +138,7 @@ var _ = Describe("OpenStackOperator controller", func() { g.Expect(version.Status.ContainerImages.HeatEngineImage).ShouldNot(BeNil()) g.Expect(version.Status.ContainerImages.InfraDnsmasqImage).ShouldNot(BeNil()) g.Expect(version.Status.ContainerImages.InfraMemcachedImage).ShouldNot(BeNil()) + g.Expect(version.Status.ContainerImages.InfraRedisImage).ShouldNot(BeNil()) g.Expect(version.Status.ContainerImages.IronicAPIImage).ShouldNot(BeNil()) g.Expect(version.Status.ContainerImages.IronicConductorImage).ShouldNot(BeNil()) g.Expect(version.Status.ContainerImages.IronicInspectorImage).ShouldNot(BeNil()) diff --git a/tests/functional/ctlplane/suite_test.go b/tests/functional/ctlplane/suite_test.go index 7366bd9cf..773ed4580 100644 --- a/tests/functional/ctlplane/suite_test.go +++ b/tests/functional/ctlplane/suite_test.go @@ -40,6 +40,7 @@ import ( 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" + redisv1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" manilav1 "github.com/openstack-k8s-operators/manila-operator/api/v1beta1" @@ -235,6 +236,8 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) err = memcachedv1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = redisv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) err = ironicv1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) err = keystonev1.AddToScheme(scheme.Scheme)