Skip to content

Commit ec1a44d

Browse files
committed
fix(monitoring): backfill status.images[].original field on startup
1 parent 63cfc34 commit ec1a44d

2 files changed

Lines changed: 85 additions & 2 deletions

File tree

cmd/main.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
2222
"sigs.k8s.io/controller-runtime/pkg/healthz"
2323
"sigs.k8s.io/controller-runtime/pkg/log/zap"
24+
"sigs.k8s.io/controller-runtime/pkg/manager"
2425
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
2526
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
2627
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -276,14 +277,19 @@ func main() {
276277
setupLog.Error(err, "unable to create controller", "controller", "ClusterReplicatedImageSetSecretOwner")
277278
os.Exit(1)
278279
}
279-
if err = (&kuikcontroller.ClusterImageSetAvailabilityReconciler{
280+
cisaReconciler := &kuikcontroller.ClusterImageSetAvailabilityReconciler{
280281
Client: mgr.GetClient(),
281282
Scheme: mgr.GetScheme(),
282283
Config: configuration,
283-
}).SetupWithManager(mgr); err != nil {
284+
}
285+
if err = cisaReconciler.SetupWithManager(mgr); err != nil {
284286
setupLog.Error(err, "unable to create controller", "controller", "ClusterImageSetAvailability")
285287
os.Exit(1)
286288
}
289+
if err = mgr.Add(manager.RunnableFunc(cisaReconciler.BackfillOriginalField)); err != nil {
290+
setupLog.Error(err, "unable to register CISA original field backfill")
291+
os.Exit(1)
292+
}
287293
// +kubebuilder:scaffold:builder
288294

289295
if metricsCertWatcher != nil {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package kuik
2+
3+
import (
4+
"context"
5+
6+
kuikv1alpha1 "github.com/enix/kube-image-keeper/api/kuik/v1alpha1"
7+
corev1 "k8s.io/api/core/v1"
8+
"sigs.k8s.io/controller-runtime/pkg/client"
9+
logf "sigs.k8s.io/controller-runtime/pkg/log"
10+
)
11+
12+
// BackfillOriginalField ensures MonitoredImage.Original is set for pre-existing
13+
// CISA status entries that were created before the Original field was introduced.
14+
// It runs once at manager startup.
15+
func (r *ClusterImageSetAvailabilityReconciler) BackfillOriginalField(ctx context.Context) error {
16+
log := logf.FromContext(ctx).WithName("backfill-original")
17+
18+
var cisaList kuikv1alpha1.ClusterImageSetAvailabilityList
19+
if err := r.List(ctx, &cisaList); err != nil {
20+
return err
21+
}
22+
23+
if len(cisaList.Items) == 0 {
24+
return nil
25+
}
26+
27+
var pods corev1.PodList
28+
if err := r.List(ctx, &pods); err != nil {
29+
return err
30+
}
31+
32+
for i := range cisaList.Items {
33+
cisa := &cisaList.Items[i]
34+
35+
needsBackfill := map[string]struct{}{}
36+
for _, image := range cisa.Status.Images {
37+
if !image.Original {
38+
needsBackfill[image.Image] = struct{}{}
39+
}
40+
}
41+
if len(needsBackfill) == 0 {
42+
continue
43+
}
44+
45+
currentImages := map[string]bool{}
46+
for j := range pods.Items {
47+
for imageName, original := range normalizedImageNamesMapFromAnnotatedPod(ctx, &pods.Items[j]) {
48+
if _, exists := needsBackfill[imageName]; exists {
49+
currentImages[imageName] = currentImages[imageName] || original
50+
}
51+
}
52+
}
53+
54+
original := cisa.DeepCopy()
55+
changed := false
56+
for j := range cisa.Status.Images {
57+
image := &cisa.Status.Images[j]
58+
if !image.Original {
59+
if isOriginal := currentImages[image.Image]; isOriginal {
60+
image.Original = true
61+
changed = true
62+
log.V(1).Info("backfilled original field", "cisa", cisa.Name, "image", image.Image)
63+
}
64+
}
65+
}
66+
67+
if changed {
68+
if err := r.Status().Patch(ctx, cisa, client.MergeFrom(original)); err != nil {
69+
log.Error(err, "failed to update CISA status after backfill", "cisa", cisa.Name)
70+
continue
71+
}
72+
log.Info("backfilled original field for CISA", "cisa", cisa.Name)
73+
}
74+
}
75+
76+
return nil
77+
}

0 commit comments

Comments
 (0)