Skip to content

Commit 5e929f1

Browse files
plaffittNicolasgouze
authored andcommitted
feat(controllers): add phase status and events to Repositories
1 parent 00b34ec commit 5e929f1

File tree

3 files changed

+85
-36
lines changed

3 files changed

+85
-36
lines changed

cmd/cache/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ func main() {
117117
os.Exit(1)
118118
}
119119
if err = (&controllers.RepositoryReconciler{
120-
Client: mgr.GetClient(),
121-
Scheme: mgr.GetScheme(),
120+
Client: mgr.GetClient(),
121+
Scheme: mgr.GetScheme(),
122+
Recorder: mgr.GetEventRecorderFor("epository-controller"),
122123
}).SetupWithManager(mgr); err != nil {
123124
setupLog.Error(err, "unable to create controller", "controller", "Repository")
124125
os.Exit(1)

controllers/cachedimage_controller.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ const (
4040
repositoryOwnerKey = ".metadata.repositoryOwner"
4141
)
4242

43+
const (
44+
cachedImagePhaseSynchronizing = "Synchronizing"
45+
cachedImagePhasePulling = "Pulling"
46+
cachedImagePhaseErrImagePull = "ErrImagePull"
47+
cachedImagePhaseReady = "Ready"
48+
cachedImagePhaseTerminating = "Terminating"
49+
)
50+
4351
// CachedImageReconciler reconciles a CachedImage object
4452
type CachedImageReconciler struct {
4553
client.Client
@@ -150,7 +158,7 @@ func (r *CachedImageReconciler) Reconcile(ctx context.Context, req ctrl.Request)
150158
// Remove image from registry when CachedImage is being deleted, finalizer is removed after it
151159
if !cachedImage.ObjectMeta.DeletionTimestamp.IsZero() {
152160
if controllerutil.ContainsFinalizer(&cachedImage, cachedImageFinalizerName) {
153-
if err := r.patchPhase(&cachedImage, "Terminating"); err != nil {
161+
if err := r.patchPhase(&cachedImage, cachedImagePhaseTerminating); err != nil {
154162
return ctrl.Result{}, err
155163
}
156164

@@ -243,7 +251,7 @@ func (r *CachedImageReconciler) Reconcile(ctx context.Context, req ctrl.Request)
243251
if err != nil {
244252
log.Error(err, "failed to cache image")
245253
r.Recorder.Eventf(&cachedImage, "Warning", "CacheFailed", "Failed to cache image %s, reason: %s", cachedImage.Spec.SourceImage, err)
246-
if phaseErr := r.patchPhase(&cachedImage, "ErrImagePull"); phaseErr != nil {
254+
if phaseErr := r.patchPhase(&cachedImage, cachedImagePhaseErrImagePull); phaseErr != nil {
247255
return ctrl.Result{}, phaseErr
248256
}
249257
return ctrl.Result{}, err
@@ -256,7 +264,7 @@ func (r *CachedImageReconciler) Reconcile(ctx context.Context, req ctrl.Request)
256264
log.Info("image already present in cache, ignoring")
257265
}
258266

259-
if err := r.patchPhase(&cachedImage, "Ready"); err != nil {
267+
if err := r.patchPhase(&cachedImage, cachedImagePhaseReady); err != nil {
260268
return ctrl.Result{}, err
261269
}
262270

@@ -315,7 +323,7 @@ func getSanitizedName(cachedImage *kuikv1alpha1.CachedImage) (string, error) {
315323
}
316324

317325
func (r *CachedImageReconciler) cacheImage(cachedImage *kuikv1alpha1.CachedImage) error {
318-
if err := r.patchPhase(cachedImage, "Synchronizing"); err != nil {
326+
if err := r.patchPhase(cachedImage, cachedImagePhaseSynchronizing); err != nil {
319327
return err
320328
}
321329

@@ -346,7 +354,7 @@ func (r *CachedImageReconciler) cacheImage(cachedImage *kuikv1alpha1.CachedImage
346354
return nil
347355
}
348356

349-
if err = r.patchPhase(cachedImage, "Pulling"); err != nil {
357+
if err = r.patchPhase(cachedImage, cachedImagePhasePulling); err != nil {
350358
return err
351359
}
352360

controllers/repository_controller.go

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1111
"k8s.io/apimachinery/pkg/runtime"
1212
"k8s.io/apimachinery/pkg/types"
13+
"k8s.io/client-go/tools/record"
1314
ctrl "sigs.k8s.io/controller-runtime"
1415
"sigs.k8s.io/controller-runtime/pkg/builder"
1516
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -31,7 +32,8 @@ const (
3132
// RepositoryReconciler reconciles a Repository object
3233
type RepositoryReconciler struct {
3334
client.Client
34-
Scheme *runtime.Scheme
35+
Scheme *runtime.Scheme
36+
Recorder record.EventRecorder
3537
}
3638

3739
//+kubebuilder:rbac:groups=kuik.enix.io,resources=repositories,verbs=get;list;watch;create;update;patch;delete
@@ -64,15 +66,20 @@ func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request)
6466
repository.Status.Images = len(cachedImageList.Items)
6567

6668
if !repository.ObjectMeta.DeletionTimestamp.IsZero() {
67-
r.UpdateStatus(ctx, &repository, []metav1.Condition{{
68-
Type: typeReadyRepository,
69-
Status: metav1.ConditionFalse,
70-
Reason: "AskedForDeletion",
71-
Message: "Repository has been asked to be deleted",
72-
}})
69+
if repository.Status.Phase != "Terminating" {
70+
r.Recorder.Eventf(&repository, "Normal", "Terminating", "Waiting for cached images to be deleted")
71+
err := r.UpdateStatus(ctx, &repository, []metav1.Condition{{
72+
Type: typeReadyRepository,
73+
Status: metav1.ConditionFalse,
74+
Reason: "Terminating",
75+
Message: "Repository has been asked to be deleted",
76+
}})
77+
if err != nil {
78+
return ctrl.Result{}, err
79+
}
80+
}
7381

7482
if controllerutil.ContainsFinalizer(&repository, repositoryFinalizerName) {
75-
7683
log.Info("repository is deleting", "cachedImages", len(cachedImageList.Items))
7784
if len(cachedImageList.Items) > 0 {
7885
return ctrl.Result{}, nil
@@ -88,13 +95,55 @@ func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request)
8895
return ctrl.Result{}, nil
8996
}
9097

98+
pullingCount := 0
99+
errImagePullCount := 0
100+
for _, cachedImage := range cachedImageList.Items {
101+
if cachedImage.Status.Phase == cachedImagePhasePulling || cachedImage.Status.Phase == cachedImagePhaseSynchronizing {
102+
pullingCount++
103+
} else if cachedImage.Status.Phase == cachedImagePhaseErrImagePull {
104+
errImagePullCount++
105+
}
106+
}
107+
108+
if errImagePullCount > 0 {
109+
err := r.UpdateStatus(ctx, &repository, []metav1.Condition{{
110+
Type: typeReadyRepository,
111+
Status: metav1.ConditionFalse,
112+
Reason: "ErrImagePull",
113+
Message: "Some images in pull error",
114+
}})
115+
if err != nil {
116+
return ctrl.Result{}, err
117+
}
118+
} else if pullingCount > 0 {
119+
err := r.UpdateStatus(ctx, &repository, []metav1.Condition{{
120+
Type: typeReadyRepository,
121+
Status: metav1.ConditionFalse,
122+
Reason: "Pulling",
123+
Message: "Some images are being cached",
124+
}})
125+
if err != nil {
126+
return ctrl.Result{}, err
127+
}
128+
} else {
129+
if repository.Status.Phase != "Ready" {
130+
r.Recorder.Eventf(&repository, "Normal", "UpToDate", "All images have been cached")
131+
}
132+
err := r.UpdateStatus(ctx, &repository, []metav1.Condition{{
133+
Type: typeReadyRepository,
134+
Status: metav1.ConditionTrue,
135+
Reason: "UpToDate",
136+
Message: "All images have been cached",
137+
}})
138+
if err != nil {
139+
return ctrl.Result{}, err
140+
}
141+
}
142+
91143
if repository.Spec.UpdateInterval != nil {
92144
nextUpdate := repository.Status.LastUpdate.Add(repository.Spec.UpdateInterval.Duration)
93145
if time.Now().After(nextUpdate) {
94146
log.Info("updating repository")
95-
if err := r.List(ctx, &cachedImageList, client.MatchingFields{repositoryOwnerKey: repository.Name}); err != nil && !apierrors.IsNotFound(err) {
96-
return ctrl.Result{}, err
97-
}
98147

99148
regexps, err := repository.CompileUpdateFilters()
100149
if err != nil {
@@ -117,16 +166,6 @@ func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request)
117166
}
118167
}
119168

120-
err := r.UpdateStatus(ctx, &repository, []metav1.Condition{{
121-
Type: typeReadyRepository,
122-
Status: metav1.ConditionTrue,
123-
Reason: "Created",
124-
Message: "Repository is ready",
125-
}})
126-
if err != nil {
127-
return ctrl.Result{}, err
128-
}
129-
130169
// Add finalizer to keep the Repository during image removal from registry on deletion
131170
if !controllerutil.ContainsFinalizer(&repository, repositoryFinalizerName) {
132171
log.Info("adding finalizer")
@@ -154,7 +193,7 @@ func (r *RepositoryReconciler) UpdateStatus(ctx context.Context, repository *kui
154193
if conditionReady.Status == metav1.ConditionTrue {
155194
repository.Status.Phase = "Ready"
156195
} else if conditionReady.Status == metav1.ConditionFalse {
157-
repository.Status.Phase = "Terminating"
196+
repository.Status.Phase = conditionReady.Reason
158197
} else {
159198
repository.Status.Phase = ""
160199
}
@@ -169,12 +208,6 @@ func (r *RepositoryReconciler) UpdateStatus(ctx context.Context, repository *kui
169208

170209
// SetupWithManager sets up the controller with the Manager.
171210
func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
172-
p := predicate.Funcs{
173-
DeleteFunc: func(e event.DeleteEvent) bool {
174-
return true
175-
},
176-
}
177-
178211
// Create an index to list CachedImage by Repository
179212
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &kuikv1alpha1.CachedImage{}, repositoryOwnerKey, func(rawObj client.Object) []string {
180213
cachedImage := rawObj.(*kuikv1alpha1.CachedImage)
@@ -198,7 +231,11 @@ func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
198231
Watches(
199232
&source.Kind{Type: &kuikv1alpha1.CachedImage{}},
200233
handler.EnqueueRequestsFromMapFunc(r.repositoryWithDeletingCachedImages),
201-
builder.WithPredicates(p),
234+
builder.WithPredicates(predicate.Funcs{
235+
DeleteFunc: func(e event.DeleteEvent) bool {
236+
return true
237+
},
238+
}),
202239
).
203240
Watches(
204241
&source.Kind{Type: &kuikv1alpha1.CachedImage{}},
@@ -207,6 +244,9 @@ func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
207244
CreateFunc: func(e event.CreateEvent) bool {
208245
return true
209246
},
247+
UpdateFunc: func(e event.UpdateEvent) bool {
248+
return true
249+
},
210250
}),
211251
).
212252
Complete(r)

0 commit comments

Comments
 (0)