Skip to content

Commit 8f4462f

Browse files
committed
Update artifact tarball when spec.ignore changes
This commit adds a new field `status.ignoreChecksum` which is used to detect changes on `spec.ignore`, that controls the exclusions for the object's `status.artifact` Signed-off-by: Tiago Angelo <[email protected]>
1 parent 5b4750b commit 8f4462f

9 files changed

+136
-5
lines changed

api/v1beta2/bucket_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ type BucketStatus struct {
124124
// +optional
125125
Artifact *Artifact `json:"artifact,omitempty"`
126126

127+
// IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
128+
// version of the object.
129+
// It is formatted as `<algo>:<checksum>`. For example: `sha256:<checksum>`.
130+
// +optional
131+
IgnoreChecksum string `json:"ignoreChecksum,omitempty"`
132+
127133
meta.ReconcileRequestStatus `json:",inline"`
128134
}
129135

api/v1beta2/gitrepository_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ type GitRepositoryStatus struct {
211211
// +optional
212212
IncludedArtifacts []*Artifact `json:"includedArtifacts,omitempty"`
213213

214+
// IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
215+
// version of the object.
216+
// It is formatted as `<algo>:<checksum>`. For example: `sha256:<checksum>`.
217+
// +optional
218+
IgnoreChecksum string `json:"ignoreChecksum,omitempty"`
219+
214220
meta.ReconcileRequestStatus `json:",inline"`
215221
}
216222

config/crd/bases/source.toolkit.fluxcd.io_buckets.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ spec:
478478
- type
479479
type: object
480480
type: array
481+
ignoreChecksum:
482+
description: 'IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
483+
version of the object. It is formatted as `<algo>:<checksum>`. For
484+
example: `sha256:<checksum>`.'
485+
type: string
481486
lastHandledReconcileAt:
482487
description: LastHandledReconcileAt holds the value of the most recent
483488
reconcile request value, so a change of the annotation value can

config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,11 @@ spec:
653653
- type
654654
type: object
655655
type: array
656+
ignoreChecksum:
657+
description: 'IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
658+
version of the object. It is formatted as `<algo>:<checksum>`. For
659+
example: `sha256:<checksum>`.'
660+
type: string
656661
includedArtifacts:
657662
description: IncludedArtifacts contains a list of the last successfully
658663
included Artifacts as instructed by GitRepositorySpec.Include.

controllers/bucket_controller.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"sync"
2929
"time"
3030

31-
"github.com/fluxcd/source-controller/pkg/azure"
3231
"golang.org/x/sync/errgroup"
3332
"golang.org/x/sync/semaphore"
3433
corev1 "k8s.io/api/core/v1"
@@ -42,6 +41,8 @@ import (
4241
"sigs.k8s.io/controller-runtime/pkg/predicate"
4342
"sigs.k8s.io/controller-runtime/pkg/ratelimiter"
4443

44+
"github.com/fluxcd/source-controller/pkg/azure"
45+
4546
"github.com/fluxcd/pkg/apis/meta"
4647
"github.com/fluxcd/pkg/runtime/conditions"
4748
helper "github.com/fluxcd/pkg/runtime/controller"
@@ -562,21 +563,31 @@ func (r *BucketReconciler) reconcileArtifact(ctx context.Context, obj *sourcev1.
562563
// Create artifact
563564
artifact := r.Storage.NewArtifactFor(obj.Kind, obj, revision, fmt.Sprintf("%s.tar.gz", revision))
564565

566+
// Calculates checksum of current .spec.ignore
567+
var ignoreChecksum string
568+
if obj.Spec.Ignore != nil {
569+
ignore := []byte(*obj.Spec.Ignore)
570+
ignoreChecksum = fmt.Sprintf("sha256:%x", sha256.Sum256(ignore))
571+
}
572+
565573
// Set the ArtifactInStorageCondition if there's no drift.
566574
defer func() {
567-
if obj.GetArtifact().HasRevision(artifact.Revision) {
575+
if obj.GetArtifact().HasRevision(artifact.Revision) && obj.Status.IgnoreChecksum == ignoreChecksum {
568576
conditions.Delete(obj, sourcev1.ArtifactOutdatedCondition)
569577
conditions.MarkTrue(obj, sourcev1.ArtifactInStorageCondition, meta.SucceededReason,
570578
"stored artifact for revision '%s'", artifact.Revision)
571579
}
572580
}()
573581

574582
// The artifact is up-to-date
575-
if obj.GetArtifact().HasRevision(artifact.Revision) {
583+
if obj.GetArtifact().HasRevision(artifact.Revision) && obj.Status.IgnoreChecksum == ignoreChecksum {
576584
r.eventLogf(ctx, obj, events.EventTypeTrace, sourcev1.ArtifactUpToDateReason, "artifact up-to-date with remote revision: '%s'", artifact.Revision)
577585
return sreconcile.ResultSuccess, nil
578586
}
579587

588+
// Ensure .spec.ignore checksum is up-to-date
589+
obj.Status.IgnoreChecksum = ignoreChecksum
590+
580591
// Ensure target path exists and is a directory
581592
if f, err := os.Stat(dir); err != nil {
582593
e := &serror.Event{

controllers/bucket_controller_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
apierrors "k8s.io/apimachinery/pkg/api/errors"
3838
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3939
"k8s.io/client-go/tools/record"
40+
"k8s.io/utils/pointer"
4041
kstatus "sigs.k8s.io/cli-utils/pkg/kstatus/status"
4142
"sigs.k8s.io/controller-runtime/pkg/client"
4243
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -977,6 +978,34 @@ func TestBucketReconciler_reconcileArtifact(t *testing.T) {
977978
*conditions.TrueCondition(sourcev1.StorageOperationFailedCondition, sourcev1.InvalidPathReason, "is not a directory"),
978979
},
979980
},
981+
{
982+
name: "Ignore checksum should be set when spec ignore is in use",
983+
beforeFunc: func(t *WithT, obj *sourcev1.Bucket, index *etagIndex, dir string) {
984+
obj.Spec.Interval = metav1.Duration{Duration: interval}
985+
obj.Spec.Ignore = pointer.StringPtr("!**.txt\n")
986+
},
987+
afterFunc: func(t *WithT, obj *sourcev1.Bucket, dir string) {
988+
t.Expect(obj.Status.IgnoreChecksum).To(Equal("sha256:539530fbd29c252e357e36ddc065dc7923265e4ea795f09cada03287288f5e7a"))
989+
},
990+
want: sreconcile.ResultSuccess,
991+
assertConditions: []metav1.Condition{
992+
*conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'"),
993+
},
994+
},
995+
{
996+
name: "Ignore checksum should be updated when spec ignore changes",
997+
beforeFunc: func(t *WithT, obj *sourcev1.Bucket, index *etagIndex, dir string) {
998+
obj.Spec.Interval = metav1.Duration{Duration: interval}
999+
obj.Status.IgnoreChecksum = "sha256:539530fbd29c252e357e36ddc065dc7923265e4ea795f09cada03287288f5e7a"
1000+
},
1001+
afterFunc: func(t *WithT, obj *sourcev1.Bucket, dir string) {
1002+
t.Expect(obj.Status.IgnoreChecksum).To(BeEmpty())
1003+
},
1004+
want: sreconcile.ResultSuccess,
1005+
assertConditions: []metav1.Condition{
1006+
*conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'"),
1007+
},
1008+
},
9801009
}
9811010

9821011
for _, tt := range tests {

controllers/gitrepository_controller.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package controllers
1818

1919
import (
2020
"context"
21+
"crypto/sha256"
2122
"errors"
2223
"fmt"
2324
"os"
@@ -498,21 +499,31 @@ func (r *GitRepositoryReconciler) reconcileArtifact(ctx context.Context,
498499
// Create potential new artifact with current available metadata
499500
artifact := r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), commit.String(), fmt.Sprintf("%s.tar.gz", commit.Hash.String()))
500501

502+
// Calculates checksum of current .spec.ignore
503+
var ignoreChecksum string
504+
if obj.Spec.Ignore != nil {
505+
ignore := []byte(*obj.Spec.Ignore)
506+
ignoreChecksum = fmt.Sprintf("sha256:%x", sha256.Sum256(ignore))
507+
}
508+
501509
// Set the ArtifactInStorageCondition if there's no drift.
502510
defer func() {
503-
if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) {
511+
if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) && obj.Status.IgnoreChecksum == ignoreChecksum {
504512
conditions.Delete(obj, sourcev1.ArtifactOutdatedCondition)
505513
conditions.MarkTrue(obj, sourcev1.ArtifactInStorageCondition, meta.SucceededReason,
506514
"stored artifact for revision '%s'", artifact.Revision)
507515
}
508516
}()
509517

510518
// The artifact is up-to-date
511-
if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) {
519+
if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) && obj.Status.IgnoreChecksum == ignoreChecksum {
512520
r.eventLogf(ctx, obj, events.EventTypeTrace, sourcev1.ArtifactUpToDateReason, "artifact up-to-date with remote revision: '%s'", artifact.Revision)
513521
return sreconcile.ResultSuccess, nil
514522
}
515523

524+
// Ensure .spec.ignore checksum is up-to-date
525+
obj.Status.IgnoreChecksum = ignoreChecksum
526+
516527
// Ensure target path exists and is a directory
517528
if f, err := os.Stat(dir); err != nil {
518529
e := &serror.Event{

controllers/gitrepository_controller_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,36 @@ func TestGitRepositoryReconciler_reconcileArtifact(t *testing.T) {
838838
*conditions.TrueCondition(sourcev1.StorageOperationFailedCondition, sourcev1.InvalidPathReason, "invalid target path"),
839839
},
840840
},
841+
{
842+
name: "Ignore checksum should be set when spec ignore is in use",
843+
dir: "testdata/git/repository",
844+
beforeFunc: func(obj *sourcev1.GitRepository) {
845+
obj.Spec.Interval = metav1.Duration{Duration: interval}
846+
obj.Spec.Ignore = pointer.StringPtr("!**.txt\n")
847+
},
848+
afterFunc: func(t *WithT, obj *sourcev1.GitRepository) {
849+
t.Expect(obj.Status.IgnoreChecksum).To(Equal("sha256:539530fbd29c252e357e36ddc065dc7923265e4ea795f09cada03287288f5e7a"))
850+
},
851+
want: sreconcile.ResultSuccess,
852+
assertConditions: []metav1.Condition{
853+
*conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision 'main/revision'"),
854+
},
855+
},
856+
{
857+
name: "Ignore checksum should be updated when spec ignore changes",
858+
dir: "testdata/git/repository",
859+
beforeFunc: func(obj *sourcev1.GitRepository) {
860+
obj.Spec.Interval = metav1.Duration{Duration: interval}
861+
obj.Status.IgnoreChecksum = "sha256:539530fbd29c252e357e36ddc065dc7923265e4ea795f09cada03287288f5e7a"
862+
},
863+
afterFunc: func(t *WithT, obj *sourcev1.GitRepository) {
864+
t.Expect(obj.Status.IgnoreChecksum).To(BeEmpty())
865+
},
866+
want: sreconcile.ResultSuccess,
867+
assertConditions: []metav1.Condition{
868+
*conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, meta.SucceededReason, "stored artifact for revision 'main/revision'"),
869+
},
870+
},
841871
}
842872
artifactSize := func(g *WithT, artifactURL string) *int64 {
843873
if artifactURL == "" {

docs/api/source.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,20 @@ Artifact
12081208
</tr>
12091209
<tr>
12101210
<td>
1211+
<code>ignoreChecksum</code><br>
1212+
<em>
1213+
string
1214+
</em>
1215+
</td>
1216+
<td>
1217+
<em>(Optional)</em>
1218+
<p>IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
1219+
version of the object.
1220+
It is formatted as <code>&lt;algo&gt;:&lt;checksum&gt;</code>. For example: <code>sha256:&lt;checksum&gt;</code>.</p>
1221+
</td>
1222+
</tr>
1223+
<tr>
1224+
<td>
12111225
<code>ReconcileRequestStatus</code><br>
12121226
<em>
12131227
<a href="https://godoc.org/github.com/fluxcd/pkg/apis/meta#ReconcileRequestStatus">
@@ -1643,6 +1657,20 @@ Artifacts as instructed by GitRepositorySpec.Include.</p>
16431657
</tr>
16441658
<tr>
16451659
<td>
1660+
<code>ignoreChecksum</code><br>
1661+
<em>
1662+
string
1663+
</em>
1664+
</td>
1665+
<td>
1666+
<em>(Optional)</em>
1667+
<p>IgnoreChecksum is a checksum of .spec.ignore in .status.observedGeneration
1668+
version of the object.
1669+
It is formatted as <code>&lt;algo&gt;:&lt;checksum&gt;</code>. For example: <code>sha256:&lt;checksum&gt;</code>.</p>
1670+
</td>
1671+
</tr>
1672+
<tr>
1673+
<td>
16461674
<code>ReconcileRequestStatus</code><br>
16471675
<em>
16481676
<a href="https://godoc.org/github.com/fluxcd/pkg/apis/meta#ReconcileRequestStatus">

0 commit comments

Comments
 (0)