@@ -29,8 +29,6 @@ import (
2929 "k8s.io/client-go/kubernetes"
3030 ctrl "sigs.k8s.io/controller-runtime"
3131 "sigs.k8s.io/controller-runtime/pkg/client"
32- "sigs.k8s.io/controller-runtime/pkg/handler"
33- "sigs.k8s.io/controller-runtime/pkg/reconcile"
3432
3533 "k8s.io/apimachinery/pkg/runtime/schema"
3634
@@ -42,6 +40,7 @@ import (
4240 "github.com/openstack-k8s-operators/openstack-operator/pkg/operator/bindata"
4341 "github.com/pkg/errors"
4442 appsv1 "k8s.io/api/apps/v1"
43+ discoveryv1 "k8s.io/api/discovery/v1"
4544 apierrors "k8s.io/apimachinery/pkg/api/errors"
4645 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4746 uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -111,6 +110,7 @@ func SetupEnv() {
111110// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete;
112111// +kubebuilder:rbac:groups="",resources=serviceaccounts;configmaps;namespaces,verbs="*"
113112// +kubebuilder:rbac:groups=core,resources=services,verbs="*";
113+ // +kubebuilder:rbac:groups=discovery.k8s.io,resources=endpointslices,verbs=get;list;watch;
114114// +kubebuilder:rbac:groups=cert-manager.io,resources=issuers,verbs=get;list;watch;create;update;patch;delete;
115115// +kubebuilder:rbac:groups=cert-manager.io,resources=certificates,verbs=get;list;watch;create;update;patch;delete;
116116// +kubebuilder:rbac:groups="monitoring.coreos.com",resources=servicemonitors,verbs=list;get;watch;update;create
@@ -271,6 +271,20 @@ func (r *OpenStackReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
271271 return ctrl.Result {}, nil
272272 }
273273
274+ // Check if Services are running and have an endpoint
275+ ctrlResult , err := r .checkServiceEndpoints (ctx , instance )
276+ if err != nil {
277+ instance .Status .Conditions .Set (condition .FalseCondition (
278+ operatorv1beta1 .OpenStackOperatorReadyCondition ,
279+ condition .ErrorReason ,
280+ condition .SeverityWarning ,
281+ operatorv1beta1 .OpenStackOperatorErrorMessage ,
282+ err ))
283+ return ctrl.Result {}, err
284+ } else if (ctrlResult != ctrl.Result {}) {
285+ return ctrlResult , nil
286+ }
287+
274288 instance .Status .Conditions .MarkTrue (
275289 operatorv1beta1 .OpenStackOperatorReadyCondition ,
276290 operatorv1beta1 .OpenStackOperatorReadyMessage )
@@ -340,6 +354,53 @@ func (r *OpenStackReconciler) countDeployments(ctx context.Context, instance *op
340354 return count , nil
341355}
342356
357+ func isWebhookEndpoint (name string ) bool {
358+ // NOTE: this is a static list for all operators with webhooks enabled
359+ endpointNames := []string {"openstack-operator-webhook-service" , "infra-operator-webhook-service" , "openstack-baremetal-operator-webhook-service" }
360+ for _ , prefix := range endpointNames {
361+ if strings .HasPrefix (name , prefix ) {
362+ return true
363+ }
364+ }
365+ return false
366+ }
367+
368+ // checkServiceEndpoints -
369+ func (r * OpenStackReconciler ) checkServiceEndpoints (ctx context.Context , instance * operatorv1beta1.OpenStack ) (ctrl.Result , error ) {
370+
371+ endpointSliceList := & discoveryv1.EndpointSliceList {}
372+ err := r .Client .List (ctx , endpointSliceList , & client.ListOptions {Namespace : instance .Namespace })
373+ if err != nil {
374+ if apierrors .IsNotFound (err ) {
375+ log .Log .Info ("Webhook endpoint not found. Requeuing..." )
376+ return ctrl.Result {RequeueAfter : time .Duration (5 ) * time .Second }, nil
377+ }
378+ return ctrl.Result {}, err
379+ }
380+
381+ for _ , endpointSlice := range endpointSliceList .Items {
382+ if isWebhookEndpoint (endpointSlice .GetName ()) {
383+ if len (endpointSlice .Endpoints ) == 0 {
384+ log .Log .Info ("Webhook endpoint not configured. Requeuing..." , "name" , endpointSlice .GetName ())
385+ return ctrl.Result {RequeueAfter : time .Duration (5 ) * time .Second }, nil
386+ }
387+ for _ , endpoint := range endpointSlice .Endpoints {
388+ if len (endpoint .Addresses ) == 0 {
389+ log .Log .Info ("Webhook endpoint addresses aren't healthy. Requeuing..." , "name" , endpointSlice .GetName ())
390+ return ctrl.Result {RequeueAfter : time .Duration (5 ) * time .Second }, nil
391+ }
392+ bFalse := false
393+ if endpoint .Conditions .Ready == & bFalse || endpoint .Conditions .Serving == & bFalse {
394+ log .Log .Info ("Webhook endpoint addresses aren't serving. Requeuing..." , "name" , endpointSlice .GetName ())
395+ return ctrl.Result {RequeueAfter : time .Duration (5 ) * time .Second }, nil
396+ }
397+ }
398+ }
399+ }
400+
401+ return ctrl.Result {}, nil
402+ }
403+
343404func (r * OpenStackReconciler ) applyManifests (ctx context.Context , instance * operatorv1beta1.OpenStack ) error {
344405 if err := r .applyCRDs (ctx , instance ); err != nil {
345406 log .Log .Error (err , "failed applying CRD manifests" )
@@ -626,38 +687,8 @@ func (r *OpenStackReconciler) postCleanupObsoleteResources(ctx context.Context,
626687// SetupWithManager sets up the controller with the Manager.
627688func (r * OpenStackReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
628689
629- deploymentFunc := handler .EnqueueRequestsFromMapFunc (func (ctx context.Context , o client.Object ) []reconcile.Request {
630- Log := r .GetLogger (ctx )
631-
632- instanceList := & operatorv1beta1.OpenStackList {}
633- err := r .Client .List (ctx , instanceList )
634- if err != nil {
635- Log .Error (err , "Unable to retrieve OpenStack instances" )
636- return nil
637- }
638-
639- if len (instanceList .Items ) == 0 {
640- return nil
641- }
642-
643- instance := & instanceList .Items [0 ]
644- if metav1 .IsControlledBy (o , instance ) {
645- Log .Info ("Reconcile request for OpenStack instance" , "instance" , instance .Name )
646- return []reconcile.Request {
647- {
648- NamespacedName : client.ObjectKey {
649- Namespace : instance .Namespace ,
650- Name : instance .Name ,
651- },
652- },
653- }
654- }
655-
656- return nil
657- })
658-
659690 return ctrl .NewControllerManagedBy (mgr ).
660- Watches (& appsv1.Deployment {}, deploymentFunc ).
691+ Owns (& appsv1.Deployment {}).
661692 For (& operatorv1beta1.OpenStack {}).
662693 Complete (r )
663694}
0 commit comments