@@ -43,6 +43,7 @@ import (
43
43
helper "github.com/fluxcd/pkg/runtime/controller"
44
44
"github.com/fluxcd/pkg/runtime/patch"
45
45
"github.com/fluxcd/pkg/runtime/predicates"
46
+ rreconcile "github.com/fluxcd/pkg/runtime/reconcile"
46
47
47
48
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
48
49
"github.com/fluxcd/source-controller/internal/cache"
@@ -109,6 +110,8 @@ type HelmRepositoryReconciler struct {
109
110
Cache * cache.Cache
110
111
TTL time.Duration
111
112
* cache.CacheRecorder
113
+
114
+ patchOptions []patch.Option
112
115
}
113
116
114
117
type HelmRepositoryReconcilerOptions struct {
@@ -120,13 +123,15 @@ type HelmRepositoryReconcilerOptions struct {
120
123
// v1beta2.HelmRepository (sub)reconcile functions. The type implementations
121
124
// are grouped and executed serially to perform the complete reconcile of the
122
125
// object.
123
- type helmRepositoryReconcileFunc func (ctx context.Context , obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , repo * repository.ChartRepository ) (sreconcile.Result , error )
126
+ type helmRepositoryReconcileFunc func (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , repo * repository.ChartRepository ) (sreconcile.Result , error )
124
127
125
128
func (r * HelmRepositoryReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
126
129
return r .SetupWithManagerAndOptions (mgr , HelmRepositoryReconcilerOptions {})
127
130
}
128
131
129
132
func (r * HelmRepositoryReconciler ) SetupWithManagerAndOptions (mgr ctrl.Manager , opts HelmRepositoryReconcilerOptions ) error {
133
+ r .patchOptions = getPatchOptions (helmRepositoryReadyCondition .Owned , r .ControllerName )
134
+
130
135
return ctrl .NewControllerManagedBy (mgr ).
131
136
For (& sourcev1.HelmRepository {}).
132
137
WithEventFilter (
@@ -160,18 +165,15 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
160
165
r .RecordSuspend (ctx , obj , obj .Spec .Suspend )
161
166
162
167
// Initialize the patch helper with the current version of the object.
163
- patchHelper , err := patch .NewHelper (obj , r .Client )
164
- if err != nil {
165
- return ctrl.Result {}, err
166
- }
168
+ serialPatcher := patch .NewSerialPatcher (obj , r .Client )
167
169
168
170
// recResult stores the abstracted reconcile result.
169
171
var recResult sreconcile.Result
170
172
171
173
// Always attempt to patch the object after each reconciliation.
172
174
// NOTE: The final runtime result and error are set in this block.
173
175
defer func () {
174
- summarizeHelper := summarize .NewHelper (r .EventRecorder , patchHelper )
176
+ summarizeHelper := summarize .NewHelper (r .EventRecorder , serialPatcher )
175
177
summarizeOpts := []summarize.Option {
176
178
summarize .WithConditions (helmRepositoryReadyCondition ),
177
179
summarize .WithReconcileResult (recResult ),
@@ -219,19 +221,36 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
219
221
r .reconcileSource ,
220
222
r .reconcileArtifact ,
221
223
}
222
- recResult , retErr = r .reconcile (ctx , obj , reconcilers )
224
+ recResult , retErr = r .reconcile (ctx , serialPatcher , obj , reconcilers )
223
225
return
224
226
}
225
227
226
228
// reconcile iterates through the helmRepositoryReconcileFunc tasks for the
227
229
// object. It returns early on the first call that returns
228
230
// reconcile.ResultRequeue, or produces an error.
229
- func (r * HelmRepositoryReconciler ) reconcile (ctx context.Context , obj * sourcev1.HelmRepository , reconcilers []helmRepositoryReconcileFunc ) (sreconcile.Result , error ) {
231
+ func (r * HelmRepositoryReconciler ) reconcile (ctx context.Context , sp * patch.SerialPatcher ,
232
+ obj * sourcev1.HelmRepository , reconcilers []helmRepositoryReconcileFunc ) (sreconcile.Result , error ) {
230
233
oldObj := obj .DeepCopy ()
231
234
232
- // Mark as reconciling if generation differs.
233
- if obj .Generation != obj .Status .ObservedGeneration {
234
- conditions .MarkReconciling (obj , "NewGeneration" , "reconciling new object generation (%d)" , obj .Generation )
235
+ rreconcile .ProgressiveStatus (false , obj , meta .ProgressingReason , "reconciliation in progress" )
236
+
237
+ var reconcileAtVal string
238
+ if v , ok := meta .ReconcileAnnotationValue (obj .GetAnnotations ()); ok {
239
+ reconcileAtVal = v
240
+ }
241
+
242
+ // Persist reconciling if generation differs or reconciliation is requested.
243
+ switch {
244
+ case obj .Generation != obj .Status .ObservedGeneration :
245
+ rreconcile .ProgressiveStatus (false , obj , meta .ProgressingReason ,
246
+ "processing object: new generation %d -> %d" , obj .Status .ObservedGeneration , obj .Generation )
247
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
248
+ return sreconcile .ResultEmpty , err
249
+ }
250
+ case reconcileAtVal != obj .Status .GetLastHandledReconcileRequest ():
251
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
252
+ return sreconcile .ResultEmpty , err
253
+ }
235
254
}
236
255
237
256
var chartRepo repository.ChartRepository
@@ -241,7 +260,7 @@ func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.
241
260
var res sreconcile.Result
242
261
var resErr error
243
262
for _ , rec := range reconcilers {
244
- recResult , err := rec (ctx , obj , & artifact , & chartRepo )
263
+ recResult , err := rec (ctx , sp , obj , & artifact , & chartRepo )
245
264
// Exit immediately on ResultRequeue.
246
265
if recResult == sreconcile .ResultRequeue {
247
266
return sreconcile .ResultRequeue , nil
@@ -311,22 +330,32 @@ func (r *HelmRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *s
311
330
// condition is added.
312
331
// The hostname of any URL in the Status of the object are updated, to ensure
313
332
// they match the Storage server hostname of current runtime.
314
- func (r * HelmRepositoryReconciler ) reconcileStorage (ctx context.Context , obj * sourcev1.HelmRepository , _ * sourcev1.Artifact , _ * repository.ChartRepository ) (sreconcile.Result , error ) {
333
+ func (r * HelmRepositoryReconciler ) reconcileStorage (ctx context.Context , sp * patch.SerialPatcher ,
334
+ obj * sourcev1.HelmRepository , _ * sourcev1.Artifact , _ * repository.ChartRepository ) (sreconcile.Result , error ) {
315
335
// Garbage collect previous advertised artifact(s) from storage
316
336
_ = r .garbageCollect (ctx , obj )
317
337
318
338
// Determine if the advertised artifact is still in storage
339
+ var artifactMissing bool
319
340
if artifact := obj .GetArtifact (); artifact != nil && ! r .Storage .ArtifactExist (* artifact ) {
320
341
obj .Status .Artifact = nil
321
342
obj .Status .URL = ""
343
+ artifactMissing = true
322
344
// Remove the condition as the artifact doesn't exist.
323
345
conditions .Delete (obj , sourcev1 .ArtifactInStorageCondition )
324
346
}
325
347
326
348
// Record that we do not have an artifact
327
349
if obj .GetArtifact () == nil {
328
- conditions .MarkReconciling (obj , "NoArtifact" , "no artifact for resource in storage" )
350
+ msg := "building artifact"
351
+ if artifactMissing {
352
+ msg += ": disappeared from storage"
353
+ }
354
+ rreconcile .ProgressiveStatus (true , obj , meta .ProgressingReason , msg )
329
355
conditions .Delete (obj , sourcev1 .ArtifactInStorageCondition )
356
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
357
+ return sreconcile .ResultEmpty , err
358
+ }
330
359
return sreconcile .ResultSuccess , nil
331
360
}
332
361
@@ -346,7 +375,8 @@ func (r *HelmRepositoryReconciler) reconcileStorage(ctx context.Context, obj *so
346
375
// If successful and the index is valid, any previous
347
376
// v1beta2.FetchFailedCondition is removed, and the repository.ChartRepository
348
377
// pointer is set to the newly fetched index.
349
- func (r * HelmRepositoryReconciler ) reconcileSource (ctx context.Context , obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , chartRepo * repository.ChartRepository ) (sreconcile.Result , error ) {
378
+ func (r * HelmRepositoryReconciler ) reconcileSource (ctx context.Context , sp * patch.SerialPatcher ,
379
+ obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , chartRepo * repository.ChartRepository ) (sreconcile.Result , error ) {
350
380
var tlsConfig * tls.Config
351
381
352
382
// Configure Helm client to access repository
@@ -455,8 +485,14 @@ func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, obj *sou
455
485
// Mark observations about the revision on the object.
456
486
if ! obj .GetArtifact ().HasRevision (chartRepo .Checksum ) {
457
487
message := fmt .Sprintf ("new index revision '%s'" , checksum )
458
- conditions .MarkTrue (obj , sourcev1 .ArtifactOutdatedCondition , "NewRevision" , message )
459
- conditions .MarkReconciling (obj , "NewRevision" , message )
488
+ if obj .GetArtifact () != nil {
489
+ conditions .MarkTrue (obj , sourcev1 .ArtifactOutdatedCondition , "NewRevision" , message )
490
+ }
491
+ rreconcile .ProgressiveStatus (true , obj , meta .ProgressingReason , "building artifact: %s" , message )
492
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
493
+ ctrl .LoggerFrom (ctx ).Error (err , "failed to patch" )
494
+ return sreconcile .ResultEmpty , err
495
+ }
460
496
}
461
497
462
498
// Create potential new artifact.
@@ -482,13 +518,13 @@ func (r *HelmRepositoryReconciler) reconcileSource(ctx context.Context, obj *sou
482
518
// early.
483
519
// On a successful archive, the Artifact in the Status of the object is set,
484
520
// and the symlink in the Storage is updated to its path.
485
- func (r * HelmRepositoryReconciler ) reconcileArtifact (ctx context.Context , obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , chartRepo * repository.ChartRepository ) (sreconcile.Result , error ) {
521
+ func (r * HelmRepositoryReconciler ) reconcileArtifact (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmRepository , artifact * sourcev1.Artifact , chartRepo * repository.ChartRepository ) (sreconcile.Result , error ) {
486
522
// Set the ArtifactInStorageCondition if there's no drift.
487
523
defer func () {
488
524
if obj .GetArtifact ().HasRevision (artifact .Revision ) {
489
525
conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
490
526
conditions .MarkTrue (obj , sourcev1 .ArtifactInStorageCondition , meta .SucceededReason ,
491
- "stored artifact for revision '%s'" , artifact .Revision )
527
+ "stored artifact: revision '%s'" , artifact .Revision )
492
528
}
493
529
494
530
chartRepo .Unload ()
0 commit comments