@@ -19,7 +19,6 @@ package controller
1919
2020import (
2121 "context"
22- "errors"
2322 "fmt"
2423 "maps"
2524 "slices"
@@ -40,7 +39,6 @@ import (
4039 "sigs.k8s.io/controller-runtime/pkg/reconcile"
4140
4241 "github.com/go-logr/logr"
43- networkv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
4442 topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
4543 keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1"
4644 common "github.com/openstack-k8s-operators/lib-common/modules/common"
@@ -61,6 +59,7 @@ import (
6159 mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1"
6260
6361 placementv1 "github.com/openstack-k8s-operators/nova-operator/api/placement/v1beta1"
62+ internalcommon "github.com/openstack-k8s-operators/nova-operator/internal/common"
6463 placement "github.com/openstack-k8s-operators/nova-operator/internal/placement"
6564
6665 appsv1 "k8s.io/api/apps/v1"
@@ -70,91 +69,6 @@ import (
7069 k8s_errors "k8s.io/apimachinery/pkg/api/errors"
7170)
7271
73- // Static errors for Application Credential handling
74- var (
75- ErrACSecretNotFound = errors .New ("ApplicationCredential secret not found" )
76- ErrACSecretMissingKeys = errors .New ("ApplicationCredential secret missing required keys" )
77- )
78-
79- type conditionUpdater interface {
80- Set (c * condition.Condition )
81- MarkTrue (t condition.Type , messageFormat string , messageArgs ... any )
82- }
83-
84- // GetSecret interface defines methods for objects that can provide secret names
85- type GetSecret interface {
86- GetSecret () string
87- client.Object
88- }
89-
90- // ensureSecret - ensures that the Secret object exists and the expected fields
91- // are in the Secret. It returns a hash of the values of the expected fields.
92- func ensureSecret (
93- ctx context.Context ,
94- secretName types.NamespacedName ,
95- expectedFields []string ,
96- reader client.Reader ,
97- conditionUpdater conditionUpdater ,
98- ) (string , ctrl.Result , corev1.Secret , error ) {
99- secret := & corev1.Secret {}
100- err := reader .Get (ctx , secretName , secret )
101- if err != nil {
102- if k8s_errors .IsNotFound (err ) {
103- // This is currently only used to acquire the password secret, which should have been
104- // manually created by the user and referenced in the spec, so we treat this as a
105- // warning because it means that the service will not be able to start.
106- conditionUpdater .Set (condition .FalseCondition (
107- condition .InputReadyCondition ,
108- condition .ErrorReason ,
109- condition .SeverityWarning ,
110- "%s" , fmt .Sprintf ("Input data resources missing: %s" , "secret/" + secretName .Name )))
111- return "" ,
112- ctrl.Result {},
113- * secret ,
114- fmt .Errorf ("%w: Secret %s not found" , err , secretName )
115- }
116- conditionUpdater .Set (condition .FalseCondition (
117- condition .InputReadyCondition ,
118- condition .ErrorReason ,
119- condition .SeverityWarning ,
120- condition .InputReadyErrorMessage ,
121- err .Error ()))
122- return "" , ctrl.Result {}, * secret , err
123- }
124-
125- // collect the secret values the caller expects to exist
126- values := [][]byte {}
127- for _ , field := range expectedFields {
128- val , ok := secret .Data [field ]
129- if ! ok {
130- err := fmt .Errorf ("%w: field '%s' not found in secret/%s" , util .ErrFieldNotFound , field , secretName .Name )
131- conditionUpdater .Set (condition .FalseCondition (
132- condition .InputReadyCondition ,
133- condition .ErrorReason ,
134- condition .SeverityWarning ,
135- condition .InputReadyErrorMessage ,
136- err .Error ()))
137- return "" , ctrl.Result {}, * secret , err
138- }
139- values = append (values , val )
140- }
141-
142- // TODO(gibi): Do we need to watch the Secret for changes?
143-
144- hash , err := util .ObjectHash (values )
145- if err != nil {
146- conditionUpdater .Set (condition .FalseCondition (
147- condition .InputReadyCondition ,
148- condition .ErrorReason ,
149- condition .SeverityWarning ,
150- condition .InputReadyErrorMessage ,
151- err .Error ()))
152- return "" , ctrl.Result {}, * secret , err
153- }
154-
155- return hash , ctrl.Result {}, * secret , nil
156- }
157-
15872// GetLogger returns a logger object with a prefix of "controller.name" and additional controller context fields
15973func (r * PlacementAPIReconciler ) GetLogger (ctx context.Context ) logr.Logger {
16074 return log .FromContext (ctx ).WithName ("Controllers" ).WithName ("PlacementAPI" )
@@ -307,34 +221,26 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request
307221 //
308222 // check for required OpenStack secret holding passwords for service/admin user and add hash to the vars map
309223 //
310- hash , result , secret , err := ensureSecret (
224+ hash , result , secret , err := internalcommon . EnsureSecret (
311225 ctx ,
312226 types.NamespacedName {Namespace : instance .Namespace , Name : instance .Spec .Secret },
313227 []string {
314228 instance .Spec .PasswordSelectors .Service ,
315229 },
316230 h .GetClient (),
317- & instance .Status .Conditions )
231+ & instance .Status .Conditions ,
232+ time .Second * 10 ,
233+ )
318234 if err != nil {
319- if k8s_errors .IsNotFound (err ) {
320- // Since the service secret should have been manually created by the user and referenced in the spec,
321- // we treat this as a warning because it means that the service will not be able to start.
322- Log .Info (fmt .Sprintf ("OpenStack secret %s not found" , instance .Spec .Secret ))
323- instance .Status .Conditions .Set (condition .FalseCondition (
324- condition .InputReadyCondition ,
325- condition .ErrorReason ,
326- condition .SeverityWarning ,
327- condition .InputReadyWaitingMessage ))
328- return ctrl.Result {RequeueAfter : time .Second * 10 }, nil
329- }
330- instance .Status .Conditions .Set (condition .FalseCondition (
331- condition .InputReadyCondition ,
332- condition .ErrorReason ,
333- condition .SeverityWarning ,
334- condition .InputReadyErrorMessage ,
335- err .Error ()))
336235 return result , err
337236 }
237+ if (result != ctrl.Result {}) {
238+ // Since the service secret should have been manually created by the user and referenced in the spec,
239+ // we treat this as a warning because it means that the service will not be able to start.
240+ // InputReady condition and requeue are already set by EnsureSecret above.
241+ Log .Info (fmt .Sprintf ("OpenStack secret %s not found" , instance .Spec .Secret ))
242+ return result , nil
243+ }
338244 configMapVars [instance .Spec .Secret ] = env .SetValue (hash )
339245
340246 // all our input checks out so report InputReady
@@ -472,7 +378,7 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request
472378
473379 instance .Status .Conditions .MarkTrue (condition .ServiceConfigReadyCondition , condition .ServiceConfigReadyMessage )
474380
475- serviceAnnotations , result , err := r . ensureNetworkAttachments (ctx , h , instance )
381+ serviceAnnotations , result , err := internalcommon . EnsureNetworkAttachments (ctx , h , instance . Spec . NetworkAttachments , & instance . Status . Conditions , time . Second * 10 )
476382 if (err != nil || result != ctrl.Result {}) {
477383 return result , err
478384 }
@@ -660,54 +566,6 @@ func (r *PlacementAPIReconciler) ensureServiceExposed(
660566 return apiEndpoints , ctrl.Result {}, nil
661567}
662568
663- func (r * PlacementAPIReconciler ) ensureNetworkAttachments (
664- ctx context.Context ,
665- h * helper.Helper ,
666- instance * placementv1.PlacementAPI ,
667- ) (map [string ]string , ctrl.Result , error ) {
668- var nadAnnotations map [string ]string
669- var err error
670-
671- Log := r .GetLogger (ctx )
672- // networks to attach to
673- nadList := []networkv1.NetworkAttachmentDefinition {}
674- for _ , netAtt := range instance .Spec .NetworkAttachments {
675- nad , err := nad .GetNADWithName (ctx , h , netAtt , instance .Namespace )
676- if err != nil {
677- if k8s_errors .IsNotFound (err ) {
678- // Since the net-attach-def CR should have been manually created by the user and referenced in the spec,
679- // we treat this as a warning because it means that the service will not be able to start.
680- Log .Info (fmt .Sprintf ("network-attachment-definition %s not found" , netAtt ))
681- instance .Status .Conditions .Set (condition .FalseCondition (
682- condition .NetworkAttachmentsReadyCondition ,
683- condition .ErrorReason ,
684- condition .SeverityWarning ,
685- condition .NetworkAttachmentsReadyWaitingMessage ,
686- netAtt ))
687- return nadAnnotations , ctrl.Result {RequeueAfter : time .Second * 10 }, nil
688- }
689- instance .Status .Conditions .Set (condition .FalseCondition (
690- condition .NetworkAttachmentsReadyCondition ,
691- condition .ErrorReason ,
692- condition .SeverityWarning ,
693- condition .NetworkAttachmentsReadyErrorMessage ,
694- err .Error ()))
695- return nadAnnotations , ctrl.Result {}, err
696- }
697-
698- if nad != nil {
699- nadList = append (nadList , * nad )
700- }
701- }
702-
703- nadAnnotations , err = nad .EnsureNetworksAnnotation (nadList )
704- if err != nil {
705- return nadAnnotations , ctrl.Result {}, fmt .Errorf ("failed create network annotation from %s: %w" ,
706- instance .Spec .NetworkAttachments , err )
707- }
708- return nadAnnotations , ctrl.Result {}, nil
709- }
710-
711569func (r * PlacementAPIReconciler ) ensureKeystoneServiceUser (
712570 ctx context.Context ,
713571 h * helper.Helper ,
@@ -1268,35 +1126,19 @@ func (r *PlacementAPIReconciler) ensureDeployment(
12681126 //
12691127 // Handle Topology
12701128 //
1271- topology , err := topologyv1 .EnsureServiceTopology (
1129+ // If TopologyRef is present and ensureServiceTopology returned a valid
1130+ // topology object, set .Status.LastAppliedTopology to the referenced one
1131+ // and mark the condition as true
1132+ topology , err := internalcommon .EnsureTopology (
12721133 ctx ,
12731134 h ,
1274- instance .Spec .TopologyRef ,
1275- instance .Status .LastAppliedTopology ,
1135+ instance ,
12761136 instance .Name ,
1137+ & instance .Status .Conditions ,
12771138 labels .GetLabelSelector (serviceLabels ),
12781139 )
12791140 if err != nil {
1280- instance .Status .Conditions .Set (condition .FalseCondition (
1281- condition .TopologyReadyCondition ,
1282- condition .ErrorReason ,
1283- condition .SeverityWarning ,
1284- condition .TopologyReadyErrorMessage ,
1285- err .Error ()))
1286- return ctrl.Result {}, fmt .Errorf ("waiting for Topology requirements: %w" , err )
1287- }
1288-
1289- // If TopologyRef is present and ensureServiceTopology returned a valid
1290- // topology object, set .Status.LastAppliedTopology to the referenced one
1291- // and mark the condition as true
1292- if instance .Spec .TopologyRef != nil {
1293- // update the Status with the last retrieved Topology name
1294- instance .Status .LastAppliedTopology = instance .Spec .TopologyRef
1295- // update the TopologyRef associated condition
1296- instance .Status .Conditions .MarkTrue (condition .TopologyReadyCondition , condition .TopologyReadyMessage )
1297- } else {
1298- // remove LastAppliedTopology from the .Status
1299- instance .Status .LastAppliedTopology = nil
1141+ return ctrl.Result {}, err
13001142 }
13011143
13021144 // Define a new Deployment object
@@ -1472,7 +1314,7 @@ func (r *PlacementAPIReconciler) generateServiceConfigMaps(
14721314 if err != nil {
14731315 if k8s_errors .IsNotFound (err ) {
14741316 h .GetLogger ().Info ("ApplicationCredential secret not found, waiting" , "secret" , instance .Spec .Auth .ApplicationCredentialSecret )
1475- return fmt .Errorf ("%w: %s" , ErrACSecretNotFound , instance .Spec .Auth .ApplicationCredentialSecret )
1317+ return fmt .Errorf ("%w: %s" , internalcommon . ErrACSecretNotFound , instance .Spec .Auth .ApplicationCredentialSecret )
14761318 }
14771319 h .GetLogger ().Error (err , "Failed to get ApplicationCredential secret" , "secret" , instance .Spec .Auth .ApplicationCredentialSecret )
14781320 return err
@@ -1481,7 +1323,7 @@ func (r *PlacementAPIReconciler) generateServiceConfigMaps(
14811323 acSecretData , okSecret := acSecretObj .Data [keystonev1 .ACSecretSecretKey ]
14821324 if ! okID || len (acID ) == 0 || ! okSecret || len (acSecretData ) == 0 {
14831325 h .GetLogger ().Info ("ApplicationCredential secret missing required keys" , "secret" , instance .Spec .Auth .ApplicationCredentialSecret )
1484- return fmt .Errorf ("%w: %s" , ErrACSecretMissingKeys , instance .Spec .Auth .ApplicationCredentialSecret )
1326+ return fmt .Errorf ("%w: %s" , internalcommon . ErrACSecretMissingKeys , instance .Spec .Auth .ApplicationCredentialSecret )
14851327 }
14861328 templateParameters ["UseApplicationCredentials" ] = true
14871329 templateParameters ["ACID" ] = string (acID )
0 commit comments