@@ -18,18 +18,23 @@ package healthcheck
1818
1919import (
2020 "context"
21- "fmt"
2221 "time"
2322
2423 appsv1 "k8s.io/api/apps/v1"
2524 corev1 "k8s.io/api/core/v1"
26- "k8s.io/apimachinery/pkg/runtime"
25+ "k8s.io/apimachinery/pkg/runtime/schema "
2726 "k8s.io/apimachinery/pkg/types"
27+
28+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+ "k8s.io/apimachinery/pkg/runtime"
30+ kerrors "k8s.io/apimachinery/pkg/util/errors"
2831 operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2"
2932 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3033 "sigs.k8s.io/cluster-api/util/conditions"
3134 "sigs.k8s.io/cluster-api/util/patch"
3235 ctrl "sigs.k8s.io/controller-runtime"
36+
37+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3338 "sigs.k8s.io/controller-runtime/pkg/builder"
3439 "sigs.k8s.io/controller-runtime/pkg/client"
3540 "sigs.k8s.io/controller-runtime/pkg/controller"
@@ -38,22 +43,76 @@ import (
3843 "sigs.k8s.io/controller-runtime/pkg/reconcile"
3944)
4045
46+ func init () {
47+ var err error
48+ deploymentPredicate , err = predicate .LabelSelectorPredicate (metav1.LabelSelector {
49+ MatchExpressions : []metav1.LabelSelectorRequirement {{
50+ Key : providerLabelKey ,
51+ Operator : metav1 .LabelSelectorOpExists ,
52+ }},
53+ })
54+ utilruntime .Must (err )
55+ }
56+
57+ const providerLabelKey = "cluster.x-k8s.io/provider"
58+
59+ var deploymentPredicate predicate.Predicate
60+
4161type ProviderHealthCheckReconciler struct {
4262 Client client.Client
4363}
4464
45- const (
46- providerLabelKey = "cluster.x-k8s.io/provider"
47- )
65+ type GenericProviderHealthCheckReconciler struct {
66+ Client client.Client
67+ Provider operatorv1.GenericProvider
68+ providerGVK schema.GroupVersionKind
69+ }
4870
4971func (r * ProviderHealthCheckReconciler ) SetupWithManager (mgr ctrl.Manager , options controller.Options ) error {
72+ return kerrors .NewAggregate ([]error {
73+ (& GenericProviderHealthCheckReconciler {
74+ Client : mgr .GetClient (),
75+ Provider : & operatorv1.CoreProvider {},
76+ }).SetupWithManager (mgr , options ),
77+ (& GenericProviderHealthCheckReconciler {
78+ Client : mgr .GetClient (),
79+ Provider : & operatorv1.InfrastructureProvider {},
80+ }).SetupWithManager (mgr , options ),
81+ (& GenericProviderHealthCheckReconciler {
82+ Client : mgr .GetClient (),
83+ Provider : & operatorv1.BootstrapProvider {},
84+ }).SetupWithManager (mgr , options ),
85+ (& GenericProviderHealthCheckReconciler {
86+ Client : mgr .GetClient (),
87+ Provider : & operatorv1.ControlPlaneProvider {},
88+ }).SetupWithManager (mgr , options ),
89+ (& GenericProviderHealthCheckReconciler {
90+ Client : mgr .GetClient (),
91+ Provider : & operatorv1.AddonProvider {},
92+ }).SetupWithManager (mgr , options ),
93+ (& GenericProviderHealthCheckReconciler {
94+ Client : mgr .GetClient (),
95+ Provider : & operatorv1.IPAMProvider {},
96+ }).SetupWithManager (mgr , options ),
97+ })
98+ }
99+
100+ func (r * GenericProviderHealthCheckReconciler ) SetupWithManager (mgr ctrl.Manager , options controller.Options ) error {
101+ kinds , _ , err := r .Client .Scheme ().ObjectKinds (r .Provider )
102+ if err != nil {
103+ return err
104+ }
105+
106+ r .providerGVK = kinds [0 ]
107+
50108 return ctrl .NewControllerManagedBy (mgr ).
51- For (& appsv1.Deployment {}, builder .WithPredicates (providerDeploymentPredicates ())).
109+ For (& appsv1.Deployment {}, builder .WithPredicates (r .providerDeploymentPredicates ())).
110+ WithEventFilter (deploymentPredicate ).
52111 WithOptions (options ).
53112 Complete (r )
54113}
55114
56- func (r * ProviderHealthCheckReconciler ) Reconcile (ctx context.Context , req reconcile.Request ) (_ reconcile.Result , reterr error ) {
115+ func (r * GenericProviderHealthCheckReconciler ) Reconcile (ctx context.Context , req reconcile.Request ) (_ reconcile.Result , reterr error ) {
57116 log := ctrl .LoggerFrom (ctx )
58117
59118 log .Info ("Checking provider health" )
@@ -67,19 +126,15 @@ func (r *ProviderHealthCheckReconciler) Reconcile(ctx context.Context, req recon
67126 return result , err
68127 }
69128
70- // There should be just one owner reference - to a Provider resource.
71- if len (deployment .GetOwnerReferences ()) != 1 {
72- return result , fmt .Errorf ("incorrect number of owner references for provider deployment %s" , req .NamespacedName )
129+ // There should be one owner pointing to the Provider resource.
130+ if err := r .Client .Get (ctx , r .getProviderKey (deployment ), r .Provider ); err != nil {
131+ // Error reading the object - requeue the request.
132+ return result , err
73133 }
74134
75- deploymentOwner := deployment .GetOwnerReferences ()[0 ]
76-
77135 deploymentAvailableCondition := getDeploymentCondition (deployment .Status , appsv1 .DeploymentAvailable )
78136
79- typedProvider , err := r .getGenericProvider (ctx , deploymentOwner .Kind , deploymentOwner .Name , req .Namespace )
80- if err != nil {
81- return result , err
82- }
137+ typedProvider := r .Provider
83138
84139 // Stop earlier if this provider is not fully installed yet.
85140 if ! conditions .IsTrue (typedProvider , operatorv1 .ProviderInstalledCondition ) {
@@ -122,52 +177,20 @@ func (r *ProviderHealthCheckReconciler) Reconcile(ctx context.Context, req recon
122177 return result , patchHelper .Patch (ctx , typedProvider , options )
123178}
124179
125- func (r * ProviderHealthCheckReconciler ) getGenericProvider (ctx context.Context , providerKind , providerName , providerNamespace string ) (operatorv1.GenericProvider , error ) {
126- switch providerKind {
127- case "CoreProvider" :
128- provider := & operatorv1.CoreProvider {}
129- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
130- return nil , err
131- }
132-
133- return provider , nil
134- case "BootstrapProvider" :
135- provider := & operatorv1.BootstrapProvider {}
136- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
137- return nil , err
138- }
139-
140- return provider , nil
141- case "ControlPlaneProvider" :
142- provider := & operatorv1.ControlPlaneProvider {}
143- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
144- return nil , err
145- }
146-
147- return provider , nil
148- case "InfrastructureProvider" :
149- provider := & operatorv1.InfrastructureProvider {}
150- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
151- return nil , err
152- }
153-
154- return provider , nil
155- case "AddonProvider" :
156- provider := & operatorv1.AddonProvider {}
157- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
158- return nil , err
180+ func (r * GenericProviderHealthCheckReconciler ) getProviderName (deploy client.Object ) string {
181+ for _ , owner := range deploy .GetOwnerReferences () {
182+ if owner .Kind == r .providerGVK .Kind {
183+ return owner .Name
159184 }
185+ }
160186
161- return provider , nil
162- case "IPAMProvider" :
163- provider := & operatorv1.IPAMProvider {}
164- if err := r .Client .Get (ctx , types.NamespacedName {Name : providerName , Namespace : providerNamespace }, provider ); err != nil {
165- return nil , err
166- }
187+ return ""
188+ }
167189
168- return provider , nil
169- default :
170- return nil , fmt .Errorf ("failed to cast interface for type: %s" , providerKind )
190+ func (r * GenericProviderHealthCheckReconciler ) getProviderKey (deploy client.Object ) types.NamespacedName {
191+ return types.NamespacedName {
192+ Namespace : deploy .GetNamespace (),
193+ Name : r .getProviderName (deploy ),
171194 }
172195}
173196
@@ -183,16 +206,14 @@ func getDeploymentCondition(status appsv1.DeploymentStatus, condType appsv1.Depl
183206 return nil
184207}
185208
186- func providerDeploymentPredicates () predicate.Funcs {
209+ func ( r * GenericProviderHealthCheckReconciler ) providerDeploymentPredicates () predicate.Funcs {
187210 isProviderDeployment := func (obj runtime.Object ) bool {
188- clusterOperator , ok := obj .(* appsv1.Deployment )
211+ deployment , ok := obj .(* appsv1.Deployment )
189212 if ! ok {
190213 panic ("expected to get an of object of type appsv1.Deployment" )
191214 }
192215
193- _ , found := clusterOperator .GetLabels ()[providerLabelKey ]
194-
195- return found
216+ return r .getProviderName (deployment ) != ""
196217 }
197218
198219 return predicate.Funcs {
0 commit comments