Skip to content
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
5 changes: 5 additions & 0 deletions internal/openstack/applicationcredential.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ func EnsureApplicationCredentialForService(

// Check if AC CR exists and is ready
if acExists {
// We want to run reconcileApplicationCredential to update the AC CR if it exists and is ready and AC config fields changed
err = reconcileApplicationCredential(ctx, helper, instance, acName, serviceUser, secretName, passwordSelector, merged)
if err != nil {
return "", ctrl.Result{}, err
}
if acCR.IsReady() {
Log.Info("Application Credential is ready", "service", serviceName, "acName", acName, "secretName", acCR.Status.SecretName)
return acCR.Status.SecretName, ctrl.Result{}, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/barbican.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
barbicanSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Barbican.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Barbican.ApplicationCredential != nil ||
instance.Spec.Barbican.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/cinder.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
cinderSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Cinder.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Cinder.ApplicationCredential != nil ||
instance.Spec.Cinder.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/designate.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
designateSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Designate.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Designate.ApplicationCredential != nil ||
instance.Spec.Designate.Template.DesignateAPI.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
5 changes: 2 additions & 3 deletions internal/openstack/glance.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,8 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl
}
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Glance.ApplicationCredential) || hasACConfigured {

// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Glance.ApplicationCredential != nil || hasACConfigured {
acSecretName, acResult, err := EnsureApplicationCredentialForService(
ctx,
helper,
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/heat.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ func ReconcileHeat(ctx context.Context, instance *corev1beta1.OpenStackControlPl
heatSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Heat.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Heat.ApplicationCredential != nil ||
instance.Spec.Heat.Template.Auth.ApplicationCredentialSecret != "" {

heatACSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
8 changes: 3 additions & 5 deletions internal/openstack/ironic.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl
ironicSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Ironic.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Ironic.ApplicationCredential != nil ||
instance.Spec.Ironic.Template.Auth.ApplicationCredentialSecret != "" ||
instance.Spec.Ironic.Template.IronicInspector.Auth.ApplicationCredentialSecret != "" {

Expand All @@ -145,7 +145,6 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl
return ctrl.Result{}, err
}

// If AC is not ready, return immediately without updating the service CR
if (acResult != ctrl.Result{}) {
return acResult, nil
}
Expand All @@ -162,7 +161,7 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl
instance,
"ironic-inspector",
ironicReady,
ironicSecret, // Inspector shares the same secret as ironic
ironicSecret,
instance.Spec.Ironic.Template.IronicInspector.PasswordSelectors.Service,
instance.Spec.Ironic.Template.IronicInspector.ServiceUser,
instance.Spec.Ironic.ApplicationCredential,
Expand All @@ -171,7 +170,6 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl
return ctrl.Result{}, err
}

// If AC is not ready, return immediately without updating the service CR
if (inspectorACResult != ctrl.Result{}) {
return inspectorACResult, nil
}
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/manila.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ func ReconcileManila(ctx context.Context, instance *corev1beta1.OpenStackControl
manilaSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Manila.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Manila.ApplicationCredential != nil ||
instance.Spec.Manila.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/neutron.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ func ReconcileNeutron(ctx context.Context, instance *corev1beta1.OpenStackContro
neutronSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Neutron.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Neutron.ApplicationCredential != nil ||
instance.Spec.Neutron.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/nova.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl
novaSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Nova.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Nova.ApplicationCredential != nil ||
instance.Spec.Nova.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
8 changes: 4 additions & 4 deletions internal/openstack/octavia.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ func ReconcileOctavia(ctx context.Context, instance *corev1beta1.OpenStackContro
octaviaSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Octavia.ApplicationCredential) ||
instance.Spec.Octavia.Template.OctaviaAPI.Auth.ApplicationCredentialSecret != "" {
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Octavia.ApplicationCredential != nil ||
instance.Spec.Octavia.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
ctx,
Expand All @@ -194,7 +194,7 @@ func ReconcileOctavia(ctx context.Context, instance *corev1beta1.OpenStackContro
// Set ApplicationCredentialSecret based on what the helper returned:
// - If AC disabled: returns ""
// - If AC enabled and ready: returns the AC secret name
instance.Spec.Octavia.Template.OctaviaAPI.Auth.ApplicationCredentialSecret = acSecretName
instance.Spec.Octavia.Template.Auth.ApplicationCredentialSecret = acSecretName
}

svcs, err := service.GetServicesListWithLabel(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/placement.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func ReconcilePlacementAPI(ctx context.Context, instance *corev1beta1.OpenStackC
placementSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Placement.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Placement.ApplicationCredential != nil ||
instance.Spec.Placement.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/swift.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ func ReconcileSwift(ctx context.Context, instance *corev1beta1.OpenStackControlP
swiftSecret = instance.Spec.Secret
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Swift.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Swift.ApplicationCredential != nil ||
instance.Spec.Swift.Template.SwiftProxy.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
22 changes: 6 additions & 16 deletions internal/openstack/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont

// AC for Aodh (if service enabled)
if instance.Spec.Telemetry.Template.Autoscaling.Enabled != nil && *instance.Spec.Telemetry.Template.Autoscaling.Enabled {
// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Telemetry.ApplicationCredentialAodh) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Telemetry.ApplicationCredentialAodh != nil ||
instance.Spec.Telemetry.Template.Autoscaling.Aodh.Auth.ApplicationCredentialSecret != "" {

// Apply same fallback logic as in CreateOrPatch to avoid passing empty values to AC
Expand Down Expand Up @@ -162,15 +162,12 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont
// - If AC enabled and ready: returns the AC secret name
instance.Spec.Telemetry.Template.Autoscaling.Aodh.Auth.ApplicationCredentialSecret = aodhACSecretName
}
} else {
// Aodh service disabled, clear the field
instance.Spec.Telemetry.Template.Autoscaling.Aodh.Auth.ApplicationCredentialSecret = ""
}

// AC for Ceilometer (if service enabled)
if instance.Spec.Telemetry.Template.Ceilometer.Enabled != nil && *instance.Spec.Telemetry.Template.Ceilometer.Enabled {
// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Telemetry.ApplicationCredentialCeilometer) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Telemetry.ApplicationCredentialCeilometer != nil ||
instance.Spec.Telemetry.Template.Ceilometer.Auth.ApplicationCredentialSecret != "" {

// Apply same fallback logic as in CreateOrPatch to avoid passing empty values to AC
Expand Down Expand Up @@ -204,15 +201,11 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont
// - If AC enabled and ready: returns the AC secret name
instance.Spec.Telemetry.Template.Ceilometer.Auth.ApplicationCredentialSecret = ceilometerACSecretName
}
} else {
// Ceilometer service disabled, clear the field
instance.Spec.Telemetry.Template.Ceilometer.Auth.ApplicationCredentialSecret = ""
}

// AC for CloudKitty (if service enabled)
if instance.Spec.Telemetry.Template.CloudKitty.Enabled != nil && *instance.Spec.Telemetry.Template.CloudKitty.Enabled {
// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Telemetry.ApplicationCredentialCloudKitty) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Telemetry.ApplicationCredentialCloudKitty != nil ||
instance.Spec.Telemetry.Template.CloudKitty.Auth.ApplicationCredentialSecret != "" {

// Apply same fallback logic as in CreateOrPatch to avoid passing empty values to AC
Expand Down Expand Up @@ -246,9 +239,6 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont
// - If AC enabled and ready: returns the AC secret name
instance.Spec.Telemetry.Template.CloudKitty.Auth.ApplicationCredentialSecret = cloudkittyACSecretName
}
} else {
// CloudKitty service disabled, clear the field
instance.Spec.Telemetry.Template.CloudKitty.Auth.ApplicationCredentialSecret = ""
}

// preserve any previously set TLS certs, set CA cert
Expand Down
4 changes: 2 additions & 2 deletions internal/openstack/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ func ReconcileWatcher(ctx context.Context, instance *corev1beta1.OpenStackContro
return ""
}

// Only call if AC enabled or currently configured
if isACEnabled(instance.Spec.ApplicationCredential, instance.Spec.Watcher.ApplicationCredential) ||
// Reconcile AC if configured (enabled or disabled) or secret previously set
if instance.Spec.Watcher.ApplicationCredential != nil ||
instance.Spec.Watcher.Template.Auth.ApplicationCredentialSecret != "" {

acSecretName, acResult, err := EnsureApplicationCredentialForService(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
apiVersion: kuttl.dev/v1beta1
kind: TestAssert
commands:
- script: |-
set -euo pipefail
NS="${NAMESPACE}"

SERVICES=(barbican cinder glance swift neutron placement nova ceilometer)

wait_deleted() {
local kind=$1 name=$2 timeout=${3:-180}
echo "Waiting for $kind/$name to be deleted..."
local end=$((SECONDS + timeout))
while [ $SECONDS -lt $end ]; do
if ! oc get "$kind" "$name" -n "$NS" &>/dev/null; then
echo "✓ $kind/$name deleted"
return 0
fi
sleep 5
done
echo "ERROR: $kind/$name still exists after ${timeout}s"
exit 1
}

echo "========================================="
echo "Testing Application Credential Cleanup"
echo "========================================="
echo

echo "=== Verifying global ApplicationCredential is disabled ==="
global_enabled=$(oc get openstackcontrolplane openstack -n "$NS" -o jsonpath='{.spec.applicationCredential.enabled}')
if [ "$global_enabled" != "false" ]; then
echo "ERROR: OpenStackControlPlane.spec.applicationCredential.enabled expected 'false', got '$global_enabled'"
exit 1
fi
echo "✓ OpenStackControlPlane.spec.applicationCredential.enabled = false"
echo

echo "=== Verifying AC CRs are deleted ==="
for svc in "${SERVICES[@]}"; do
wait_deleted appcred "ac-$svc" 180
done
echo

echo "=== Verifying AC Secrets are cleaned up ==="
for svc in "${SERVICES[@]}"; do
wait_deleted secret "ac-$svc-secret" 120
done
echo

echo "All ApplicationCredential CRs and Secrets cleaned up successfully"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
commands:
- script: |
oc patch openstackcontrolplane openstack -n $NAMESPACE --type merge -p '{"spec":{"applicationCredential":{"enabled":false}}}'