@@ -26,35 +26,33 @@ import (
2626 corev1 "k8s.io/api/core/v1"
2727 policyv1 "k8s.io/api/policy/v1"
2828 "k8s.io/apimachinery/pkg/api/meta"
29- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3029 "k8s.io/apimachinery/pkg/runtime"
3130 "k8s.io/apimachinery/pkg/util/intstr"
31+ apps1ac "k8s.io/client-go/applyconfigurations/apps/v1"
32+ corev1ac "k8s.io/client-go/applyconfigurations/core/v1"
33+ v1 "k8s.io/client-go/applyconfigurations/meta/v1"
34+ policyv1ac "k8s.io/client-go/applyconfigurations/policy/v1"
3235 "k8s.io/client-go/util/retry"
3336 ctrl "sigs.k8s.io/controller-runtime"
3437 k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
35- "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil "
38+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil "
3639 logger "sigs.k8s.io/controller-runtime/pkg/log"
3740
38- "github.com/gophercloud/gophercloud/v2"
39-
4041 kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
41- "github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack"
4242)
4343
4444type GardenerNodeLifecycleController struct {
4545 k8sclient.Client
46- Scheme * runtime.Scheme
47- serviceClient * gophercloud.ServiceClient
48- namespace string
46+ Scheme * runtime.Scheme
47+ namespace string
4948}
5049
5150const (
52- labelDeployment = "cobaltcore-maintenance-controller"
53- maintenancePodsNamespace = "kube-system"
54- labelCriticalComponent = "node.gardener.cloud/critical-component"
55- labelCriticalComponentsNotReady = "node.gardener.cloud/critical-components-not-ready"
56- valueReasonTerminating = "terminating"
57- MaintenanceControllerName = "maintenance"
51+ labelDeployment = "cobaltcore-maintenance-controller"
52+ maintenancePodsNamespace = "kube-system"
53+ labelCriticalComponent = "node.gardener.cloud/critical-component"
54+ valueReasonTerminating = "terminating"
55+ MaintenanceControllerName = "maintenance"
5856)
5957
6058// The counter-side in gardener is here:
@@ -116,26 +114,20 @@ func (r *GardenerNodeLifecycleController) Reconcile(ctx context.Context, req ctr
116114
117115func (r * GardenerNodeLifecycleController ) ensureBlockingPodDisruptionBudget (ctx context.Context , node * corev1.Node , minAvailable int32 ) error {
118116 name := nameForNode (node )
119- podDisruptionBudget := & policyv1.PodDisruptionBudget {
120- ObjectMeta : metav1.ObjectMeta {
121- Name : name ,
122- Namespace : maintenancePodsNamespace ,
123- },
117+ nodeLabels := labelsForNode (node )
118+ gvk , err := apiutil .GVKForObject (node , r .Scheme )
119+ if err != nil {
120+ return err
124121 }
125122
126- _ , err := controllerutil .CreateOrUpdate (ctx , r .Client , podDisruptionBudget , func () error {
127- minAvail := intstr .FromInt32 (minAvailable )
128- nodeLabels := labelsForNode (node )
129- podDisruptionBudget .Labels = nodeLabels
130- podDisruptionBudget .Spec = policyv1.PodDisruptionBudgetSpec {
131- MinAvailable : & minAvail ,
132- Selector : & metav1.LabelSelector {
133- MatchLabels : nodeLabels ,
134- },
135- }
136- return controllerutil .SetControllerReference (node , podDisruptionBudget , r .Scheme )
137- })
138- return err
123+ podDisruptionBudget := policyv1ac .PodDisruptionBudget (name , maintenancePodsNamespace ).
124+ WithLabels (nodeLabels ).
125+ WithOwnerReferences (OwnerReference (node , & gvk )).
126+ WithSpec (policyv1ac .PodDisruptionBudgetSpec ().
127+ WithMinAvailable (intstr .FromInt32 (minAvailable )).
128+ WithSelector (v1 .LabelSelector ().WithMatchLabels (nodeLabels )))
129+
130+ return r .Apply (ctx , podDisruptionBudget , k8sclient .FieldOwner (MaintenanceControllerName ))
139131}
140132
141133func isTerminating (node * corev1.Node ) bool {
@@ -166,86 +158,63 @@ func labelsForNode(node *corev1.Node) map[string]string {
166158
167159func (r * GardenerNodeLifecycleController ) ensureSignallingDeployment (ctx context.Context , node * corev1.Node , scale int32 , ready bool ) error {
168160 name := nameForNode (node )
169- deployment := & appsv1.Deployment {
170- ObjectMeta : metav1.ObjectMeta {
171- Name : name ,
172- Namespace : maintenancePodsNamespace ,
173- },
174- }
161+ labels := labelsForNode (node )
175162
176- _ , err := controllerutil .CreateOrUpdate (ctx , r .Client , deployment , func () error {
177- labels := labelsForNode (node )
178- deployment .Labels = labels
163+ podLabels := maps .Clone (labels )
164+ podLabels [labelCriticalComponent ] = "true"
179165
180- podLabels := maps .Clone (labels )
181- podLabels [labelCriticalComponent ] = "true"
166+ var command string
167+ if ready {
168+ command = "/bin/true"
169+ } else {
170+ command = "/bin/false"
171+ }
182172
183- var command []string
184- if ready {
185- command = []string {"/bin/true" }
186- } else {
187- command = []string {"/bin/false" }
188- }
173+ gvk , err := apiutil .GVKForObject (node , r .Scheme )
174+ if err != nil {
175+ return err
176+ }
189177
190- var one int64 = 1
191- zeroStr := intstr .FromInt (0 )
192- oneStr := intstr .FromInt (1 )
193-
194- deployment .Spec = appsv1.DeploymentSpec {
195- Replicas : & scale ,
196- Selector : & metav1.LabelSelector {
197- MatchLabels : labels ,
198- },
199- Strategy : appsv1.DeploymentStrategy {
200- Type : appsv1 .RollingUpdateDeploymentStrategyType ,
201- RollingUpdate : & appsv1.RollingUpdateDeployment {
202- MaxUnavailable : & zeroStr ,
203- MaxSurge : & oneStr ,
204- },
205- },
206- Template : corev1.PodTemplateSpec {
207- ObjectMeta : metav1.ObjectMeta {
208- Labels : podLabels ,
209- },
210- Spec : corev1.PodSpec {
211- HostNetwork : true , // to make it run as early as possible
212- NodeSelector : map [string ]string {
178+ deployment := apps1ac .Deployment (name , maintenancePodsNamespace ).
179+ WithOwnerReferences (OwnerReference (node , & gvk )).
180+ WithLabels (labels ).
181+ WithSpec (apps1ac .DeploymentSpec ().
182+ WithReplicas (scale ).
183+ WithSelector (v1 .LabelSelector ().
184+ WithMatchLabels (labels )).
185+ WithStrategy (apps1ac .DeploymentStrategy ().
186+ WithRollingUpdate (apps1ac .RollingUpdateDeployment ().
187+ WithMaxUnavailable (intstr .FromInt (0 )).
188+ WithMaxSurge (intstr .FromInt (1 )))).
189+ WithTemplate (corev1ac .PodTemplateSpec ().
190+ WithLabels (podLabels ).
191+ WithSpec (corev1ac .PodSpec ().
192+ WithHostNetwork (true ).
193+ WithNodeSelector (map [string ]string {
213194 corev1 .LabelHostname : node .Labels [corev1 .LabelHostname ],
214- },
215- TerminationGracePeriodSeconds : & one , // busybox sleep doesn't handle TERM so well as pid 1
216- Tolerations : []corev1.Toleration {
217- {
218- Effect : corev1 .TaintEffectNoExecute ,
219- Operator : corev1 .TolerationOpExists ,
220- },
221- {
222- Effect : corev1 .TaintEffectNoSchedule ,
223- Operator : corev1 .TolerationOpExists ,
224- },
225- },
226- Containers : []corev1.Container {
227- {
228- Name : "sleep" ,
229- Image : "keppel.global.cloud.sap/ccloud-dockerhub-mirror/library/busybox:latest" ,
230- Command : []string {"sleep" , "inf" },
231- // We need apparently retry to get the timing of the container being up correct
232- // The startup probe makes sure that we only need to poll this for the (hopefully)
233- // non-standard case of the host not being integrated yet
234- StartupProbe : & corev1.Probe {
235- ProbeHandler : corev1.ProbeHandler {Exec : & corev1.ExecAction {Command : command }},
236- InitialDelaySeconds : 0 ,
237- PeriodSeconds : 1 ,
238- SuccessThreshold : 1 ,
239- FailureThreshold : 1 ,
240- },
241- },
242- },
243- },
244- },
245- }
246- return controllerutil .SetControllerReference (node , deployment , r .Scheme )
247- })
248- return err
195+ }).
196+ WithTerminationGracePeriodSeconds (1 ).
197+ WithTolerations (
198+ corev1ac .Toleration ().
199+ WithEffect (corev1 .TaintEffectNoExecute ).
200+ WithOperator (corev1 .TolerationOpExists ),
201+ corev1ac .Toleration ().
202+ WithEffect (corev1 .TaintEffectNoSchedule ).
203+ WithOperator (corev1 .TolerationOpExists ),
204+ ).
205+ WithContainers (
206+ corev1ac .Container ().
207+ WithName ("sleep" ).
208+ WithImage ("keppel.global.cloud.sap/ccloud-dockerhub-mirror/library/busybox:latest" ).
209+ WithCommand ("sleep" , "inf" ).
210+ WithStartupProbe (corev1ac .Probe ().
211+ WithExec (corev1ac .ExecAction ().WithCommand (command )).
212+ WithInitialDelaySeconds (0 ).
213+ WithPeriodSeconds (0 ).
214+ WithFailureThreshold (1 ).
215+ WithSuccessThreshold (1 ))))))
216+
217+ return r .Apply (ctx , deployment , k8sclient .FieldOwner (MaintenanceControllerName ))
249218}
250219
251220// SetupWithManager sets up the controller with the Manager.
@@ -254,11 +223,6 @@ func (r *GardenerNodeLifecycleController) SetupWithManager(mgr ctrl.Manager, nam
254223 _ = logger .FromContext (ctx )
255224 r .namespace = namespace
256225
257- var err error
258- if r .serviceClient , err = openstack .GetServiceClient (ctx , "compute" , nil ); err != nil {
259- return err
260- }
261-
262226 return ctrl .NewControllerManagedBy (mgr ).
263227 Named (MaintenanceControllerName ).
264228 For (& corev1.Node {}).
0 commit comments