@@ -5,7 +5,6 @@ package container_image
55
66import (
77 "context"
8- "reflect"
98
109 "go.mondoo.com/mondoo-operator/api/v1alpha2"
1110 "go.mondoo.com/mondoo-operator/pkg/utils/k8s"
@@ -16,6 +15,7 @@ import (
1615 "k8s.io/apimachinery/pkg/labels"
1716 ctrl "sigs.k8s.io/controller-runtime"
1817 "sigs.k8s.io/controller-runtime/pkg/client"
18+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1919)
2020
2121var logger = ctrl .Log .WithName ("k8s-images-scanning" )
@@ -71,56 +71,31 @@ func (n *DeploymentHandler) syncCronJob(ctx context.Context) error {
7171 return err
7272 }
7373
74- updated , err := n .syncConfigMap (ctx , clusterUid )
75- if err != nil {
74+ if err := n .syncConfigMap (ctx , clusterUid ); err != nil {
7675 return err
7776 }
7877
79- // TODO: for CronJob we might consider triggering the CronJob now after the ConfigMap has been changed. It will make sense from the
80- // user perspective to want to run the jobs after you have updated the config.
81- if updated {
82- logger .Info (
83- "Inventory ConfigMap was just updated. The job will use the new config during the next scheduled run." ,
84- "namespace" , n .Mondoo .Namespace ,
85- "name" , CronJobName (n .Mondoo .Name ))
86- }
87-
8878 // Reconcile private registry secrets (merges multiple secrets if needed)
8979 privateRegistrySecretName , err := k8s .ReconcilePrivateRegistriesSecret (ctx , n .KubeClient , n .Mondoo )
9080 if err != nil {
9181 logger .Error (err , "Failed to reconcile private registry secrets" )
9282 return err
9383 }
9484
95- existing := & batchv1.CronJob {}
9685 desired := CronJob (mondooClientImage , integrationMrn , clusterUid , privateRegistrySecretName , n .Mondoo , * n .MondooOperatorConfig )
97- if err := ctrl .SetControllerReference (n .Mondoo , desired , n .KubeClient .Scheme ()); err != nil {
98- logger .Error (err , "Failed to set ControllerReference" , "namespace" , desired .Namespace , "name" , desired .Name )
99- return err
100- }
101-
102- created , err := k8s .CreateIfNotExist (ctx , n .KubeClient , existing , desired )
86+ obj := & batchv1.CronJob {ObjectMeta : metav1.ObjectMeta {Name : desired .Name , Namespace : desired .Namespace }}
87+ op , err := k8s .CreateOrUpdate (ctx , n .KubeClient , obj , n .Mondoo , logger , func () error {
88+ k8s .UpdateCronJobFields (obj , desired )
89+ return nil
90+ })
10391 if err != nil {
104- logger .Error (err , "Failed to create CronJob" , "namespace" , desired .Namespace , "name" , desired .Name )
10592 return err
10693 }
10794
108- if created {
109- logger .Info ("Created CronJob" , "namespace" , desired .Namespace , "name" , desired .Name )
110- } else if ! k8s .AreCronJobsEqual (* existing , * desired ) {
111- existing .Spec .JobTemplate = desired .Spec .JobTemplate
112- existing .Spec .Schedule = desired .Spec .Schedule
113- existing .Spec .ConcurrencyPolicy = desired .Spec .ConcurrencyPolicy
114- existing .SetOwnerReferences (desired .GetOwnerReferences ())
115-
116- // Remove completed/failed jobs because they won't be updated when the cronjob changes.
117- // Active jobs are preserved to avoid killing in-progress scans.
95+ // When a CronJob is updated, remove completed Jobs so they don't linger with stale config
96+ if op == controllerutil .OperationResultUpdated {
11897 if err := k8s .DeleteCompletedJobs (ctx , n .KubeClient , n .Mondoo .Namespace , CronJobLabels (* n .Mondoo ), logger ); err != nil {
119- return err
120- }
121-
122- if err := n .KubeClient .Update (ctx , existing ); err != nil {
123- logger .Error (err , "Failed to update CronJob" , "namespace" , existing .Namespace , "name" , existing .Name )
98+ logger .Error (err , "Failed to clean up completed Jobs after CronJob update" )
12499 return err
125100 }
126101 }
@@ -154,53 +129,29 @@ func (n *DeploymentHandler) syncCronJob(ctx context.Context) error {
154129 return nil
155130}
156131
157- // syncConfigMap syncs the inventory ConfigMap. Returns a boolean indicating whether the ConfigMap has been updated. It
158- // can only be "true", if the ConfigMap existed before this reconcile cycle and the inventory was different from the
159- // desired state.
160- func (n * DeploymentHandler ) syncConfigMap (ctx context.Context , clusterUid string ) (bool , error ) {
161- existing := & corev1.ConfigMap {}
162-
132+ func (n * DeploymentHandler ) syncConfigMap (ctx context.Context , clusterUid string ) error {
163133 integrationMrn , err := k8s .TryGetIntegrationMrnForAuditConfig (ctx , n .KubeClient , * n .Mondoo )
164134 if err != nil {
165135 logger .Error (err , "failed to retrieve IntegrationMRN" )
166- return false , err
136+ return err
167137 }
168138
169139 desired , err := ConfigMap (integrationMrn , clusterUid , * n .Mondoo , * n .MondooOperatorConfig )
170140 if err != nil {
171141 logger .Error (err , "failed to generate desired ConfigMap with inventory" )
172- return false , err
173- }
174-
175- if err := ctrl .SetControllerReference (n .Mondoo , desired , n .KubeClient .Scheme ()); err != nil {
176- logger .Error (err , "Failed to set ControllerReference" , "namespace" , desired .Namespace , "name" , desired .Name )
177- return false , err
178- }
179-
180- created , err := k8s .CreateIfNotExist (ctx , n .KubeClient , existing , desired )
181- if err != nil {
182- logger .Error (err , "Failed to create inventory ConfigMap" , "namespace" , desired .Namespace , "name" , desired .Name )
183- return false , err
142+ return err
184143 }
185144
186- if created {
187- logger .Info ("Created inventory ConfigMap" , "namespace" , desired .Namespace , "name" , desired .Name )
188- return false , nil
145+ obj := & corev1.ConfigMap {ObjectMeta : metav1.ObjectMeta {Name : desired .Name , Namespace : desired .Namespace }}
146+ if _ , err := k8s .CreateOrUpdate (ctx , n .KubeClient , obj , n .Mondoo , logger , func () error {
147+ obj .Labels = desired .Labels
148+ obj .Data = desired .Data
149+ return nil
150+ }); err != nil {
151+ return err
189152 }
190153
191- updated := false
192- if existing .Data ["inventory" ] != desired .Data ["inventory" ] ||
193- ! reflect .DeepEqual (existing .GetOwnerReferences (), desired .GetOwnerReferences ()) {
194- existing .Data ["inventory" ] = desired .Data ["inventory" ]
195- existing .SetOwnerReferences (desired .GetOwnerReferences ())
196-
197- if err := n .KubeClient .Update (ctx , existing ); err != nil {
198- logger .Error (err , "Failed to update inventory ConfigMap" , "namespace" , existing .Namespace , "name" , existing .Name )
199- return false , err
200- }
201- updated = true
202- }
203- return updated , nil
154+ return nil
204155}
205156
206157func (n * DeploymentHandler ) getCronJobsForAuditConfig (ctx context.Context ) ([]batchv1.CronJob , error ) {
0 commit comments