@@ -301,6 +301,42 @@ func (r *OctaviaAPIReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma
301301 return err
302302 }
303303
304+ // Application Credential secret watching function
305+ acSecretFn := func (_ context.Context , o client.Object ) []reconcile.Request {
306+ name := o .GetName ()
307+ ns := o .GetNamespace ()
308+ result := []reconcile.Request {}
309+
310+ // Only handle Secret objects
311+ if _ , isSecret := o .(* corev1.Secret ); ! isSecret {
312+ return nil
313+ }
314+
315+ // Check if this is an octavia AC secret by name pattern (ac-octavia-secret)
316+ expectedSecretName := keystonev1 .GetACSecretName (octavia .ServiceName )
317+ if name == expectedSecretName {
318+ // get all OctaviaAPI CRs in this namespace
319+ octaviaAPIs := & octaviav1.OctaviaAPIList {}
320+ listOpts := []client.ListOption {
321+ client .InNamespace (ns ),
322+ }
323+ if err := r .List (context .Background (), octaviaAPIs , listOpts ... ); err != nil {
324+ return nil
325+ }
326+
327+ // Enqueue reconcile for all octavia API instances
328+ for _ , cr := range octaviaAPIs .Items {
329+ objKey := client.ObjectKey {
330+ Namespace : ns ,
331+ Name : cr .Name ,
332+ }
333+ result = append (result , reconcile.Request {NamespacedName : objKey })
334+ }
335+ }
336+
337+ return result
338+ }
339+
304340 return ctrl .NewControllerManagedBy (mgr ).
305341 For (& octaviav1.OctaviaAPI {}).
306342 Owns (& keystonev1.KeystoneService {}).
@@ -316,6 +352,8 @@ func (r *OctaviaAPIReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma
316352 handler .EnqueueRequestsFromMapFunc (r .findObjectsForSrc ),
317353 builder .WithPredicates (predicate.ResourceVersionChangedPredicate {}),
318354 ).
355+ Watches (& corev1.Secret {},
356+ handler .EnqueueRequestsFromMapFunc (acSecretFn )).
319357 Watches (& topologyv1.Topology {},
320358 handler .EnqueueRequestsFromMapFunc (r .findObjectsForSrc ),
321359 builder .WithPredicates (predicate.GenerationChangedPredicate {})).
@@ -650,6 +688,19 @@ func (r *OctaviaAPIReconciler) reconcileNormal(ctx context.Context, instance *oc
650688 // Secrets
651689 secretsVars := make (map [string ]env.Setter )
652690
691+ // Verify Application Credentials if available
692+ ctrlResult , err := keystonev1 .VerifyApplicationCredentialsForService (
693+ ctx ,
694+ r .Client ,
695+ instance .Namespace ,
696+ octavia .ServiceName ,
697+ & secretsVars ,
698+ 10 * time .Second ,
699+ )
700+ if (err != nil || ctrlResult != ctrl.Result {}) {
701+ return ctrlResult , err
702+ }
703+
653704 //
654705 // TLS input validation
655706 //
@@ -722,7 +773,7 @@ func (r *OctaviaAPIReconciler) reconcileNormal(ctx context.Context, instance *oc
722773 // - %-scripts secret holding scripts to e.g. bootstrap the service
723774 // - %-config secret holding minimal octavia config required to get the service up, user can add additional files to be added to the service
724775 //
725- err : = r .generateServiceSecrets (ctx , instance , helper , & secretsVars )
776+ err = r .generateServiceSecrets (ctx , instance , helper , & secretsVars )
726777 if err != nil {
727778 instance .Status .Conditions .Set (condition .FalseCondition (
728779 condition .ServiceConfigReadyCondition ,
@@ -794,7 +845,7 @@ func (r *OctaviaAPIReconciler) reconcileNormal(ctx context.Context, instance *oc
794845 }
795846
796847 // Handle service init
797- ctrlResult , err : = r .reconcileInit (ctx , instance , helper , serviceLabels )
848+ ctrlResult , err = r .reconcileInit (ctx , instance , helper , serviceLabels )
798849 if err != nil {
799850 return ctrlResult , err
800851 } else if (ctrlResult != ctrl.Result {}) {
@@ -1105,6 +1156,17 @@ func (r *OctaviaAPIReconciler) generateServiceSecrets(
11051156 templateParameters ["TenantDomainName" ] = instance .Spec .TenantDomainName
11061157 templateParameters ["KeystoneInternalURL" ] = keystoneInternalURL
11071158 templateParameters ["KeystonePublicURL" ] = keystonePublicURL
1159+
1160+ // Check for Application Credentials
1161+ if acData , err := keystonev1 .GetApplicationCredentialFromSecret (ctx , h .GetClient (), instance .Namespace , octavia .ServiceName ); err != nil {
1162+ Log .Error (err , "Failed to get ApplicationCredential for service" , "service" , octavia .ServiceName )
1163+ return err
1164+ } else if acData != nil {
1165+ templateParameters ["ApplicationCredentialID" ] = acData .ID
1166+ templateParameters ["ApplicationCredentialSecret" ] = acData .Secret
1167+ Log .Info ("Using ApplicationCredentials auth" , "service" , octavia .ServiceName )
1168+ }
1169+
11081170 templateParameters ["NBConnection" ], err = nbCluster .GetInternalEndpoint ()
11091171 if err != nil {
11101172 return err
0 commit comments