@@ -30,6 +30,8 @@ import (
30
30
31
31
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
32
32
soci "github.com/fluxcd/source-controller/internal/oci"
33
+ "github.com/google/go-containerregistry/pkg/authn"
34
+ "github.com/google/go-containerregistry/pkg/v1/remote"
33
35
helmgetter "helm.sh/helm/v3/pkg/getter"
34
36
helmreg "helm.sh/helm/v3/pkg/registry"
35
37
corev1 "k8s.io/api/core/v1"
@@ -56,9 +58,8 @@ import (
56
58
helper "github.com/fluxcd/pkg/runtime/controller"
57
59
"github.com/fluxcd/pkg/runtime/patch"
58
60
"github.com/fluxcd/pkg/runtime/predicates"
61
+ rreconcile "github.com/fluxcd/pkg/runtime/reconcile"
59
62
"github.com/fluxcd/pkg/untar"
60
- "github.com/google/go-containerregistry/pkg/authn"
61
- "github.com/google/go-containerregistry/pkg/v1/remote"
62
63
63
64
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
64
65
"github.com/fluxcd/source-controller/internal/cache"
@@ -133,6 +134,8 @@ type HelmChartReconciler struct {
133
134
Cache * cache.Cache
134
135
TTL time.Duration
135
136
* cache.CacheRecorder
137
+
138
+ patchOptions []patch.Option
136
139
}
137
140
138
141
func (r * HelmChartReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
@@ -147,9 +150,11 @@ type HelmChartReconcilerOptions struct {
147
150
// helmChartReconcileFunc is the function type for all the v1beta2.HelmChart
148
151
// (sub)reconcile functions. The type implementations are grouped and
149
152
// executed serially to perform the complete reconcile of the object.
150
- type helmChartReconcileFunc func (ctx context.Context , obj * sourcev1.HelmChart , build * chart.Build ) (sreconcile.Result , error )
153
+ type helmChartReconcileFunc func (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmChart , build * chart.Build ) (sreconcile.Result , error )
151
154
152
155
func (r * HelmChartReconciler ) SetupWithManagerAndOptions (mgr ctrl.Manager , opts HelmChartReconcilerOptions ) error {
156
+ r .patchOptions = getPatchOptions (helmChartReadyCondition .Owned , r .ControllerName )
157
+
153
158
if err := mgr .GetCache ().IndexField (context .TODO (), & sourcev1.HelmRepository {}, sourcev1 .HelmRepositoryURLIndexKey ,
154
159
r .indexHelmRepositoryByURL ); err != nil {
155
160
return fmt .Errorf ("failed setting index fields: %w" , err )
@@ -200,18 +205,15 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
200
205
r .RecordSuspend (ctx , obj , obj .Spec .Suspend )
201
206
202
207
// Initialize the patch helper with the current version of the object.
203
- patchHelper , err := patch .NewHelper (obj , r .Client )
204
- if err != nil {
205
- return ctrl.Result {}, err
206
- }
208
+ serialPatcher := patch .NewSerialPatcher (obj , r .Client )
207
209
208
210
// recResult stores the abstracted reconcile result.
209
211
var recResult sreconcile.Result
210
212
211
213
// Always attempt to patch the object after each reconciliation.
212
214
// NOTE: The final runtime result and error are set in this block.
213
215
defer func () {
214
- summarizeHelper := summarize .NewHelper (r .EventRecorder , patchHelper )
216
+ summarizeHelper := summarize .NewHelper (r .EventRecorder , serialPatcher )
215
217
summarizeOpts := []summarize.Option {
216
218
summarize .WithConditions (helmChartReadyCondition ),
217
219
summarize .WithBiPolarityConditionTypes (sourcev1 .SourceVerifiedCondition ),
@@ -259,19 +261,35 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
259
261
r .reconcileSource ,
260
262
r .reconcileArtifact ,
261
263
}
262
- recResult , retErr = r .reconcile (ctx , obj , reconcilers )
264
+ recResult , retErr = r .reconcile (ctx , serialPatcher , obj , reconcilers )
263
265
return
264
266
}
265
267
266
268
// reconcile iterates through the helmChartReconcileFunc tasks for the
267
269
// object. It returns early on the first call that returns
268
270
// reconcile.ResultRequeue, or produces an error.
269
- func (r * HelmChartReconciler ) reconcile (ctx context.Context , obj * sourcev1.HelmChart , reconcilers []helmChartReconcileFunc ) (sreconcile.Result , error ) {
271
+ func (r * HelmChartReconciler ) reconcile (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmChart , reconcilers []helmChartReconcileFunc ) (sreconcile.Result , error ) {
270
272
oldObj := obj .DeepCopy ()
271
273
272
- // Mark as reconciling if generation differs.
273
- if obj .Generation != obj .Status .ObservedGeneration {
274
- conditions .MarkReconciling (obj , "NewGeneration" , "reconciling new object generation (%d)" , obj .Generation )
274
+ rreconcile .ProgressiveStatus (false , obj , meta .ProgressingReason , "reconciliation in progress" )
275
+
276
+ var reconcileAtVal string
277
+ if v , ok := meta .ReconcileAnnotationValue (obj .GetAnnotations ()); ok {
278
+ reconcileAtVal = v
279
+ }
280
+
281
+ // Persist reconciling if generation differs or reconciliation is requested.
282
+ switch {
283
+ case obj .Generation != obj .Status .ObservedGeneration :
284
+ rreconcile .ProgressiveStatus (false , obj , meta .ProgressingReason ,
285
+ "processing object: new generation %d -> %d" , obj .Status .ObservedGeneration , obj .Generation )
286
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
287
+ return sreconcile .ResultEmpty , err
288
+ }
289
+ case reconcileAtVal != obj .Status .GetLastHandledReconcileRequest ():
290
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
291
+ return sreconcile .ResultEmpty , err
292
+ }
275
293
}
276
294
277
295
// Run the sub-reconcilers and build the result of reconciliation.
@@ -281,7 +299,7 @@ func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmC
281
299
resErr error
282
300
)
283
301
for _ , rec := range reconcilers {
284
- recResult , err := rec (ctx , obj , & build )
302
+ recResult , err := rec (ctx , sp , obj , & build )
285
303
// Exit immediately on ResultRequeue.
286
304
if recResult == sreconcile .ResultRequeue {
287
305
return sreconcile .ResultRequeue , nil
@@ -344,22 +362,31 @@ func (r *HelmChartReconciler) notify(ctx context.Context, oldObj, newObj *source
344
362
// condition is added.
345
363
// The hostname of any URL in the Status of the object are updated, to ensure
346
364
// they match the Storage server hostname of current runtime.
347
- func (r * HelmChartReconciler ) reconcileStorage (ctx context.Context , obj * sourcev1.HelmChart , build * chart.Build ) (sreconcile.Result , error ) {
365
+ func (r * HelmChartReconciler ) reconcileStorage (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmChart , build * chart.Build ) (sreconcile.Result , error ) {
348
366
// Garbage collect previous advertised artifact(s) from storage
349
367
_ = r .garbageCollect (ctx , obj )
350
368
351
369
// Determine if the advertised artifact is still in storage
370
+ var artifactMissing bool
352
371
if artifact := obj .GetArtifact (); artifact != nil && ! r .Storage .ArtifactExist (* artifact ) {
353
372
obj .Status .Artifact = nil
354
373
obj .Status .URL = ""
374
+ artifactMissing = true
355
375
// Remove the condition as the artifact doesn't exist.
356
376
conditions .Delete (obj , sourcev1 .ArtifactInStorageCondition )
357
377
}
358
378
359
379
// Record that we do not have an artifact
360
380
if obj .GetArtifact () == nil {
361
- conditions .MarkReconciling (obj , "NoArtifact" , "no artifact for resource in storage" )
381
+ msg := "building artifact"
382
+ if artifactMissing {
383
+ msg += ": disappeared from storage"
384
+ }
385
+ rreconcile .ProgressiveStatus (true , obj , meta .ProgressingReason , msg )
362
386
conditions .Delete (obj , sourcev1 .ArtifactInStorageCondition )
387
+ if err := sp .Patch (ctx , obj , r .patchOptions ... ); err != nil {
388
+ return sreconcile .ResultEmpty , err
389
+ }
363
390
return sreconcile .ResultSuccess , nil
364
391
}
365
392
@@ -371,7 +398,7 @@ func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, obj *sourcev
371
398
return sreconcile .ResultSuccess , nil
372
399
}
373
400
374
- func (r * HelmChartReconciler ) reconcileSource (ctx context.Context , obj * sourcev1.HelmChart , build * chart.Build ) (_ sreconcile.Result , retErr error ) {
401
+ func (r * HelmChartReconciler ) reconcileSource (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmChart , build * chart.Build ) (_ sreconcile.Result , retErr error ) {
375
402
// Remove any failed verification condition.
376
403
// The reason is that a failing verification should be recalculated.
377
404
if conditions .IsFalse (obj , sourcev1 .SourceVerifiedCondition ) {
@@ -418,7 +445,7 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, obj *sourcev1
418
445
// Defer observation of build result
419
446
defer func () {
420
447
// Record both success and error observations on the object
421
- observeChartBuild (obj , build , retErr )
448
+ observeChartBuild (ctx , sp , r . patchOptions , obj , build , retErr )
422
449
423
450
// If we actually build a chart, take a historical note of any dependencies we resolved.
424
451
// The reason this is a done conditionally, is because if we have a cached one in storage,
@@ -810,7 +837,7 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
810
837
// early.
811
838
// On a successful archive, the Artifact in the Status of the object is set,
812
839
// and the symlink in the Storage is updated to its path.
813
- func (r * HelmChartReconciler ) reconcileArtifact (ctx context.Context , obj * sourcev1.HelmChart , b * chart.Build ) (sreconcile.Result , error ) {
840
+ func (r * HelmChartReconciler ) reconcileArtifact (ctx context.Context , sp * patch. SerialPatcher , obj * sourcev1.HelmChart , b * chart.Build ) (sreconcile.Result , error ) {
814
841
// Without a complete chart build, there is little to reconcile
815
842
if ! b .Complete () {
816
843
return sreconcile .ResultRequeue , nil
@@ -1265,10 +1292,16 @@ func (r *HelmChartReconciler) eventLogf(ctx context.Context, obj runtime.Object,
1265
1292
}
1266
1293
1267
1294
// observeChartBuild records the observation on the given given build and error on the object.
1268
- func observeChartBuild (obj * sourcev1.HelmChart , build * chart.Build , err error ) {
1295
+ func observeChartBuild (ctx context. Context , sp * patch. SerialPatcher , pOpts []patch. Option , obj * sourcev1.HelmChart , build * chart.Build , err error ) {
1269
1296
if build .HasMetadata () {
1270
1297
if build .Name != obj .Status .ObservedChartName || ! obj .GetArtifact ().HasRevision (build .Version ) {
1271
- conditions .MarkTrue (obj , sourcev1 .ArtifactOutdatedCondition , "NewChart" , build .Summary ())
1298
+ if obj .GetArtifact () != nil {
1299
+ conditions .MarkTrue (obj , sourcev1 .ArtifactOutdatedCondition , "NewChart" , build .Summary ())
1300
+ }
1301
+ rreconcile .ProgressiveStatus (true , obj , meta .ProgressingReason , "building artifact: %s" , build .Summary ())
1302
+ if err := sp .Patch (ctx , obj , pOpts ... ); err != nil {
1303
+ ctrl .LoggerFrom (ctx ).Error (err , "failed to patch" )
1304
+ }
1272
1305
}
1273
1306
}
1274
1307
0 commit comments