Skip to content
This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/controller/ca_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func reconcileCABundleConfigMap(h *common_helper.Helper, ctx context.Context, in

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: CABundleConfigMapName,
Name: CABundleConfigMapName(instance.Name),

@lpiwowar lpiwowar Jun 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Do we really want the operator to accept multiple OpenStackLightspeed instances at this point? Just a thread for a discussion. I remember we initially wanted to support only one OpenStackLightspeed instance.

The opposite direction would be to allow only one instance of OpenStackLightspeed at this point (e.g., accept one single instance with a specific name openstack-lightspeed).

Namespace: h.GetBeforeObject().GetNamespace(),
},
}
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/ca_bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ func TestReconcileCABundle_MergesServiceCA(t *testing.T) {

resultCM := &corev1.ConfigMap{}
err = h.GetClient().Get(ctx, types.NamespacedName{
Name: CABundleConfigMapName,
Name: CABundleConfigMapName("test-instance"),
Namespace: "test-ns",
}, resultCM)
if err != nil {
Expand Down Expand Up @@ -620,7 +620,7 @@ func TestReconcileCABundle_DeduplicatesAcrossSources(t *testing.T) {

resultCM := &corev1.ConfigMap{}
err = h.GetClient().Get(ctx, types.NamespacedName{
Name: CABundleConfigMapName,
Name: CABundleConfigMapName("test-instance"),
Namespace: "test-ns",
}, resultCM)
if err != nil {
Expand Down
13 changes: 6 additions & 7 deletions internal/controller/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@ func getRawClient(helper *common_helper.Helper) (client.Client, error) {
return rawClient, nil
}

// generateAppServerSelectorLabels returns a map of labels used as selectors
// for the application server pods.
func generateAppServerSelectorLabels() map[string]string {
func generateAppServerSelectorLabels(instanceName string) map[string]string {
return map[string]string{
"app.kubernetes.io/component": "app-server",
"app.kubernetes.io/instance": instanceName,
"app.kubernetes.io/managed-by": "openstack-lightspeed-operator",
"app.kubernetes.io/name": "openstack-lightspeed-app-server",
"app.kubernetes.io/part-of": "openstack-lightspeed",
Expand Down Expand Up @@ -92,10 +91,10 @@ func providerNameToEnvVarName(providerName string) string {
return name
}

// generatePostgresSelectorLabels returns selector labels for Postgres components.
func generatePostgresSelectorLabels() map[string]string {
func generatePostgresSelectorLabels(instanceName string) map[string]string {
return map[string]string{
"app.kubernetes.io/component": "postgres-server",
"app.kubernetes.io/instance": instanceName,
"app.kubernetes.io/managed-by": "openstack-lightspeed-operator",
"app.kubernetes.io/name": "openstack-lightspeed-service-postgres",
"app.kubernetes.io/part-of": "openstack-lightspeed",
Expand All @@ -120,10 +119,10 @@ func isDeploymentReady(deploy *appsv1.Deployment) bool {
deploy.Status.Replicas == replicas
}

// generateOKPSelectorLabels returns selector labels for OKP components.
func generateOKPSelectorLabels() map[string]string {
func generateOKPSelectorLabels(instanceName string) map[string]string {
return map[string]string{
"app.kubernetes.io/component": "okp-server",
"app.kubernetes.io/instance": instanceName,
"app.kubernetes.io/managed-by": "openstack-lightspeed-operator",
"app.kubernetes.io/name": "openstack-lightspeed-okp-server",
"app.kubernetes.io/part-of": "openstack-lightspeed",
Expand Down
25 changes: 12 additions & 13 deletions internal/controller/console_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
)

// generateConsoleSelectorLabels returns a map of labels used as selectors
// for the console plugin pods.
func generateConsoleSelectorLabels() map[string]string {
func generateConsoleSelectorLabels(instanceName string) map[string]string {
return map[string]string{
"app.kubernetes.io/component": "console-plugin",
"app.kubernetes.io/instance": instanceName,
"app.kubernetes.io/managed-by": "openstack-lightspeed-operator",
"app.kubernetes.io/name": "lightspeed-console-plugin",
"app.kubernetes.io/part-of": "openstack-lightspeed",
Expand All @@ -48,10 +47,10 @@ const consoleLocalesPath = "/usr/share/nginx/html/locales/en/" + consoleLocalesF
// buildConsoleDeploymentSpec builds the Deployment spec for the console plugin.
// Includes an init container that rewrites OpenShift references to OpenStack
// in the locales JSON file using an emptyDir volume.
func buildConsoleDeploymentSpec(consoleImage string) appsv1.DeploymentSpec {
func buildConsoleDeploymentSpec(instanceName string, consoleImage string) appsv1.DeploymentSpec {
replicas := int32(1)
volumeDefaultMode := VolumeDefaultMode
labels := generateConsoleSelectorLabels()
labels := generateConsoleSelectorLabels(instanceName)

return appsv1.DeploymentSpec{
Replicas: &replicas,
Expand All @@ -69,7 +68,7 @@ func buildConsoleDeploymentSpec(consoleImage string) appsv1.DeploymentSpec {
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
ServiceAccountName: ConsoleUIServiceAccountName,
ServiceAccountName: ConsoleUIServiceAccountName(instanceName),
InitContainers: []corev1.Container{
{
Name: "rewrite-locales",
Expand Down Expand Up @@ -159,7 +158,7 @@ func buildConsoleDeploymentSpec(consoleImage string) appsv1.DeploymentSpec {
Name: "lightspeed-console-plugin-cert",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: ConsoleUIServiceCertSecretName,
SecretName: ConsoleUIServiceCertSecretName(instanceName),
DefaultMode: &volumeDefaultMode,
},
},
Expand All @@ -169,7 +168,7 @@ func buildConsoleDeploymentSpec(consoleImage string) appsv1.DeploymentSpec {
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: ConsoleUIConfigMapName,
Name: ConsoleUIConfigMapName(instanceName),
},
DefaultMode: &volumeDefaultMode,
},
Expand All @@ -194,11 +193,11 @@ func buildConsoleDeploymentSpec(consoleImage string) appsv1.DeploymentSpec {
}

// buildConsolePluginSpec builds the ConsolePlugin spec with backend and proxy configuration.
func buildConsolePluginSpec(namespace string) consolev1.ConsolePluginSpec {
func buildConsolePluginSpec(instanceName string, namespace string) consolev1.ConsolePluginSpec {
return consolev1.ConsolePluginSpec{
Backend: consolev1.ConsolePluginBackend{
Service: &consolev1.ConsolePluginService{
Name: ConsoleUIServiceName,
Name: ConsoleUIServiceName(instanceName),
Namespace: namespace,
Port: ConsoleUIHTTPSPort,
BasePath: "/",
Expand All @@ -215,7 +214,7 @@ func buildConsolePluginSpec(namespace string) consolev1.ConsolePluginSpec {
Authorization: consolev1.UserToken,
Endpoint: consolev1.ConsolePluginProxyEndpoint{
Service: &consolev1.ConsolePluginProxyServiceConfig{
Name: OpenStackLightspeedAppServerServiceName,
Name: OpenStackLightspeedAppServerServiceName(instanceName),
Namespace: namespace,
Port: OpenStackLightspeedAppServerServicePort,
},
Expand All @@ -232,10 +231,10 @@ func buildConsoleNginxConfig() string {
}

// buildConsoleNetworkPolicySpec builds the NetworkPolicy spec for the console plugin.
func buildConsoleNetworkPolicySpec() networkingv1.NetworkPolicySpec {
func buildConsoleNetworkPolicySpec(instanceName string) networkingv1.NetworkPolicySpec {
return networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: generateConsoleSelectorLabels(),
MatchLabels: generateConsoleSelectorLabels(instanceName),
},
Ingress: []networkingv1.NetworkPolicyIngressRule{
{
Expand Down
60 changes: 31 additions & 29 deletions internal/controller/console_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ func ReconcileConsoleDeployment(h *common_helper.Helper, ctx context.Context, in
}

// reconcileConsoleConfigMap ensures the console plugin nginx ConfigMap exists.
func reconcileConsoleConfigMap(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleConfigMap(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUIConfigMapName,
Name: ConsoleUIConfigMapName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
},
}
Expand All @@ -95,18 +95,18 @@ func reconcileConsoleConfigMap(h *common_helper.Helper, ctx context.Context, _ *
}

// reconcileConsoleNetworkPolicy ensures the console plugin network policy exists.
func reconcileConsoleNetworkPolicy(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleNetworkPolicy(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

np := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUINetworkPolicyName,
Name: ConsoleUINetworkPolicyName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
},
}

result, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), np, func() error {
np.Spec = buildConsoleNetworkPolicySpec()
np.Spec = buildConsoleNetworkPolicySpec(instance.Name)
return controllerutil.SetControllerReference(h.GetBeforeObject(), np, h.GetScheme())
})

Expand All @@ -119,12 +119,12 @@ func reconcileConsoleNetworkPolicy(h *common_helper.Helper, ctx context.Context,
}

// reconcileConsoleServiceAccount ensures the console plugin service account exists.
func reconcileConsoleServiceAccount(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleServiceAccount(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

sa := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUIServiceAccountName,
Name: ConsoleUIServiceAccountName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
},
}
Expand Down Expand Up @@ -181,20 +181,20 @@ func resolveConsoleImage(ctx context.Context, h *common_helper.Helper) string {
}

// reconcileConsoleDeploymentResource ensures the console plugin deployment exists.
func reconcileConsoleDeploymentResource(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleDeploymentResource(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

consoleImage := resolveConsoleImage(ctx, h)

deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUIDeploymentName,
Name: ConsoleUIDeploymentName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
},
}

result, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), deployment, func() error {
spec := buildConsoleDeploymentSpec(consoleImage)
spec := buildConsoleDeploymentSpec(instance.Name, consoleImage)
deployment.Spec.Replicas = spec.Replicas
deployment.Spec.Selector = spec.Selector
deployment.Spec.Template = spec.Template
Expand All @@ -210,18 +210,18 @@ func reconcileConsoleDeploymentResource(h *common_helper.Helper, ctx context.Con
}

// reconcileConsoleService ensures the console plugin service exists.
func reconcileConsoleService(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleService(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUIServiceName,
Name: ConsoleUIServiceName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
},
}

result, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), svc, func() error {
svc.Spec.Selector = generateConsoleSelectorLabels()
svc.Spec.Selector = generateConsoleSelectorLabels(instance.Name)
svc.Spec.Ports = []corev1.ServicePort{
{
Port: ConsoleUIHTTPSPort,
Expand All @@ -235,7 +235,7 @@ func reconcileConsoleService(h *common_helper.Helper, ctx context.Context, _ *ap
if svc.Annotations == nil {
svc.Annotations = make(map[string]string)
}
svc.Annotations[ServingCertSecretAnnotationKey] = ConsoleUIServiceCertSecretName
svc.Annotations[ServingCertSecretAnnotationKey] = ConsoleUIServiceCertSecretName(instance.Name)

return controllerutil.SetControllerReference(h.GetBeforeObject(), svc, h.GetScheme())
})
Expand All @@ -250,12 +250,12 @@ func reconcileConsoleService(h *common_helper.Helper, ctx context.Context, _ *ap

// reconcileConsoleTLSSecret waits for the console TLS secret to be populated by
// the service-ca operator.
func reconcileConsoleTLSSecret(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsoleTLSSecret(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()
logger.Info("waiting for console TLS secret", "name", ConsoleUIServiceCertSecretName)
logger.Info("waiting for console TLS secret", "name", ConsoleUIServiceCertSecretName(instance.Name))

secretKey := client.ObjectKey{
Name: ConsoleUIServiceCertSecretName,
Name: ConsoleUIServiceCertSecretName(instance.Name),
Namespace: h.GetBeforeObject().GetNamespace(),
}

Expand All @@ -275,23 +275,23 @@ func reconcileConsoleTLSSecret(h *common_helper.Helper, ctx context.Context, _ *
return fmt.Errorf("%w: %v", ErrReconcileConsoleTLSSecret, err)
}

logger.Info("Console TLS secret is ready", "name", ConsoleUIServiceCertSecretName)
logger.Info("Console TLS secret is ready", "name", ConsoleUIServiceCertSecretName(instance.Name))
return nil
}

// reconcileConsolePlugin ensures the ConsolePlugin CR exists.
func reconcileConsolePlugin(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileConsolePlugin(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()
namespace := h.GetBeforeObject().GetNamespace()

plugin := &consolev1.ConsolePlugin{
ObjectMeta: metav1.ObjectMeta{
Name: ConsoleUIPluginName,
Name: ConsoleUIPluginName(instance.Name),
},
}

result, err := controllerutil.CreateOrPatch(ctx, h.GetClient(), plugin, func() error {
plugin.Spec = buildConsolePluginSpec(namespace)
plugin.Spec = buildConsolePluginSpec(instance.Name, namespace)
// ConsolePlugin is cluster-scoped, no owner reference
return nil
})
Expand All @@ -305,8 +305,9 @@ func reconcileConsolePlugin(h *common_helper.Helper, ctx context.Context, _ *api
}

// activateConsole adds the console plugin to the Console CR's plugin list.
func activateConsole(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func activateConsole(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()
pluginName := ConsoleUIPluginName(instance.Name)

err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
console := &openshiftv1.Console{}
Expand All @@ -320,9 +321,9 @@ func activateConsole(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1
}

if console.Spec.Plugins == nil {
console.Spec.Plugins = []string{ConsoleUIPluginName}
} else if !slices.Contains(console.Spec.Plugins, ConsoleUIPluginName) {
console.Spec.Plugins = append(console.Spec.Plugins, ConsoleUIPluginName)
console.Spec.Plugins = []string{pluginName}
} else if !slices.Contains(console.Spec.Plugins, pluginName) {
console.Spec.Plugins = append(console.Spec.Plugins, pluginName)
} else {
return nil
}
Expand All @@ -338,8 +339,9 @@ func activateConsole(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1
}

// reconcileDeleteConsole deactivates the console plugin and deletes the ConsolePlugin CR.
func reconcileDeleteConsole(h *common_helper.Helper, ctx context.Context, _ *apiv1beta1.OpenStackLightspeed) error {
func reconcileDeleteConsole(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()
pluginName := ConsoleUIPluginName(instance.Name)

// Deactivate: remove plugin from Console CR
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
Expand All @@ -356,12 +358,12 @@ func reconcileDeleteConsole(h *common_helper.Helper, ctx context.Context, _ *api
if console.Spec.Plugins == nil {
return nil
}
if !slices.Contains(console.Spec.Plugins, ConsoleUIPluginName) {
if !slices.Contains(console.Spec.Plugins, pluginName) {
return nil
}

console.Spec.Plugins = slices.DeleteFunc(console.Spec.Plugins, func(name string) bool {
return name == ConsoleUIPluginName
return name == pluginName
})

return h.GetClient().Update(ctx, console)
Expand All @@ -373,7 +375,7 @@ func reconcileDeleteConsole(h *common_helper.Helper, ctx context.Context, _ *api

// Delete ConsolePlugin CR
plugin := &consolev1.ConsolePlugin{}
err = h.GetClient().Get(ctx, client.ObjectKey{Name: ConsoleUIPluginName}, plugin)
err = h.GetClient().Get(ctx, client.ObjectKey{Name: pluginName}, plugin)
if err != nil {
if errors.IsNotFound(err) {
logger.Info("ConsolePlugin not found, skip deletion")
Expand Down
Loading
Loading