From 117d93b0798b7607105fdcf8e237c12fae2d41ee Mon Sep 17 00:00:00 2001 From: Martin Schuppert Date: Mon, 7 Aug 2023 18:16:57 +0200 Subject: [PATCH] Create nova route and svc endpoint overrides Creates the route for the nova components, also allows to customize the route via override. Generats the service override for the env with what is configured in the externalEndpoints, or specified in the service template override. Depends-On: https://github.com/openstack-k8s-operators/lib-common/pull/313 Depends-On: https://github.com/openstack-k8s-operators/keystone-operator/pull/289 Depends-On: https://github.com/openstack-k8s-operators/nova-operator/pull/489 Jira: OSP-26690 --- ....openstack.org_openstackcontrolplanes.yaml | 207 ++++++++++++++++++ apis/core/v1beta1/conditions.go | 3 + .../v1beta1/openstackcontrolplane_types.go | 18 ++ apis/core/v1beta1/zz_generated.deepcopy.go | 24 ++ ....openstack.org_openstackcontrolplanes.yaml | 207 ++++++++++++++++++ ...controlplane_galera_network_isolation.yaml | 33 ++- ...ne_galera_network_isolation_3replicas.yaml | 33 ++- ...enstackcontrolplane_network_isolation.yaml | 33 ++- ...ckcontrolplane_network_isolation_ceph.yaml | 33 ++- pkg/openstack/nova.go | 128 +++++++++++ 10 files changed, 675 insertions(+), 44 deletions(-) diff --git a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml index ec96ffba4..9f753c725 100644 --- a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -6780,6 +6780,213 @@ spec: type: object nova: properties: + apiOverride: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + cellOverride: + additionalProperties: + properties: + noVNCProxy: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + type: object + type: object enabled: default: true type: boolean diff --git a/apis/core/v1beta1/conditions.go b/apis/core/v1beta1/conditions.go index 4ee19903b..b252d731f 100644 --- a/apis/core/v1beta1/conditions.go +++ b/apis/core/v1beta1/conditions.go @@ -66,6 +66,9 @@ const ( // OpenStackControlPlaneNovaReadyCondition Status=True condition which indicates if Nova is configured and operational OpenStackControlPlaneNovaReadyCondition condition.Type = "OpenStackControlPlaneNovaReady" + // OpenStackControlPlaneExposeNovaReadyCondition Status=True condition which indicates if Nova is exposed via a route + OpenStackControlPlaneExposeNovaReadyCondition condition.Type = "OpenStackControlPlaneExposeNovaReady" + // OpenStackControlPlaneHeatReadyCondition Status=True condition which indicates if Heat is configured and operational OpenStackControlPlaneHeatReadyCondition condition.Type = "OpenStackControlPlaneHeatReady" diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index af4198fc9..ef5cdc204 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -428,6 +428,24 @@ type NovaSection struct { //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Nova services Template novav1.NovaSpec `json:"template,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // APIOverride, provides the ability to override the generated manifest of several child resources. + APIOverride Override `json:"apiOverride,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // CellOverride, provides the ability to override the generated manifest of several child resources + // for a nova cell. cell0 never have compute nodes and therefore it won't have a noVNCProxy deployed. + // Providing an override for cell0 noVNCProxy does not have an effect. + CellOverride map[string]NovaCellOverrideSpec `json:"cellOverride,omitempty"` +} + +// NovaCellOverrideSpec to override the generated manifest of several child resources. +type NovaCellOverrideSpec struct { + // +kubebuilder:validation:Optional + NoVNCProxy Override `json:"noVNCProxy,omitempty"` } // HeatSection defines the desired state of Heat services diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index 061524fe9..74831e057 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -281,10 +281,34 @@ func (in *NeutronSection) DeepCopy() *NeutronSection { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NovaCellOverrideSpec) DeepCopyInto(out *NovaCellOverrideSpec) { + *out = *in + in.NoVNCProxy.DeepCopyInto(&out.NoVNCProxy) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaCellOverrideSpec. +func (in *NovaCellOverrideSpec) DeepCopy() *NovaCellOverrideSpec { + if in == nil { + return nil + } + out := new(NovaCellOverrideSpec) + in.DeepCopyInto(out) + return out +} + // 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) + in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.CellOverride != nil { + in, out := &in.CellOverride, &out.CellOverride + *out = make(map[string]NovaCellOverrideSpec, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaSection. diff --git a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml index ec96ffba4..9f753c725 100644 --- a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -6780,6 +6780,213 @@ spec: type: object nova: properties: + apiOverride: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + cellOverride: + additionalProperties: + properties: + noVNCProxy: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + type: object + type: object enabled: default: true type: boolean diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml index bc7fa78ad..ac24b1ca5 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml @@ -127,20 +127,31 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: 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 431fa9d03..ed6a6c322 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml @@ -127,20 +127,31 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml index 231959a78..3f72ddac9 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml @@ -115,20 +115,31 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml index e3d35115a..a6120d642 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml @@ -160,20 +160,31 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/pkg/openstack/nova.go b/pkg/openstack/nova.go index 6ff791b9d..13e13b14e 100644 --- a/pkg/openstack/nova.go +++ b/pkg/openstack/nova.go @@ -20,14 +20,20 @@ import ( "context" "fmt" + "github.com/openstack-k8s-operators/lib-common/modules/common" "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/service" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" novav1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1" corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1" + k8s_errors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" ) @@ -45,9 +51,127 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl return res, err } instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneNovaReadyCondition) + instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition) return ctrl.Result{}, nil } + // add selector to service overrides + for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { + // NovaAPI + if instance.Spec.Nova.Template.APIServiceTemplate.Override.Service == nil { + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service = map[service.Endpoint]service.RoutedOverrideSpec{} + } + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service[endpointType] = + AddServiceComponentLabel( + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service[endpointType], + nova.Name+"-api") + + // cell NoVNCProxy service override + for cellName, cellTemplate := range instance.Spec.Nova.Template.CellTemplates { + // skip adding override for all the cells where novncproxy is disabled + if cellTemplate.NoVNCProxyServiceTemplate.Enabled == ptr.To(false) { + continue + } + if cellTemplate.NoVNCProxyServiceTemplate.Override.Service == nil { + cellTemplate.NoVNCProxyServiceTemplate.Override.Service = &service.RoutedOverrideSpec{} + } + + *cellTemplate.NoVNCProxyServiceTemplate.Override.Service = + AddServiceComponentLabel( + *cellTemplate.NoVNCProxyServiceTemplate.Override.Service, + getNoVNCProxyServiceLabel(nova.Name, cellName)) + + instance.Spec.Nova.Template.CellTemplates[cellName] = cellTemplate + } + } + + // When component services got created check if there is the need to create a route + if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: "nova", Namespace: instance.Namespace}, nova); err != nil { + if !k8s_errors.IsNotFound(err) { + return ctrl.Result{}, err + } + } + + // Nova API + if nova.Status.Conditions.IsTrue(novav1.NovaAPIReadyCondition) { + svcs, err := service.GetServicesListWithLabel( + ctx, + helper, + instance.Namespace, + map[string]string{common.AppSelector: nova.Name + "-api"}, + ) + if err != nil { + return ctrl.Result{}, err + } + + var ctrlResult reconcile.Result + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service, ctrlResult, err = EnsureRoute( + ctx, + instance, + helper, + nova, + svcs, + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service, + instance.Spec.Nova.APIOverride.Route, + corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + } + + if nova.Status.Conditions.IsTrue(novav1.NovaAllCellsReadyCondition) { + // cell NoVNCProxy + for cellName, cellTemplate := range instance.Spec.Nova.Template.CellTemplates { + // skip checking for/creating route if service is not enabled + if cellTemplate.NoVNCProxyServiceTemplate.Enabled == ptr.To(false) { + continue + } + + if cellTemplate.NoVNCProxyServiceTemplate.Override.Service == nil { + cellTemplate.NoVNCProxyServiceTemplate.Override.Service = &service.RoutedOverrideSpec{} + } + + svcs, err := service.GetServicesListWithLabel( + ctx, + helper, + instance.Namespace, + map[string]string{ + common.AppSelector: getNoVNCProxyServiceLabel(nova.Name, cellName), + }, + ) + if err != nil { + return ctrl.Result{}, err + } + + var ctrlResult reconcile.Result + routedOverrideSpec, ctrlResult, err := EnsureRoute( + ctx, + instance, + helper, + nova, + svcs, + map[service.Endpoint]service.RoutedOverrideSpec{ + service.EndpointInternal: *cellTemplate.NoVNCProxyServiceTemplate.Override.Service, + }, + instance.Spec.Nova.CellOverride[cellName].NoVNCProxy.Route, + corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + + cellTemplate.NoVNCProxyServiceTemplate.Override.Service = ptr.To(routedOverrideSpec[service.EndpointInternal]) + + instance.Spec.Nova.Template.CellTemplates[cellName] = cellTemplate + + } + } + helper.GetLogger().Info("Reconciling Nova", "Nova.Namespace", instance.Namespace, "Nova.Name", nova.Name) op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), nova, func() error { // 1) @@ -100,3 +224,7 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl return ctrl.Result{}, nil } + +func getNoVNCProxyServiceLabel(name string, cellName string) string { + return name + "-novncproxy-" + cellName +}