Skip to content

Commit 010dfc1

Browse files
committed
OCIRepoReconciler: no-op reconcile improvements
Introduce contentConfigChecksum in the OCIRepository status to store a checksum of the values that affect the source artifact. It is used to detect when to rebuild an artifact when the spec changes. The considerations for this are similar to the GitRepository reconciler no-op clone implementation. Both reconcileSource and reconcileArtifact need to consider the source configuration change when deciding if the artifact in the storage is up-to-date. Adds tests for reconcileSource and reconcileArtifact for the noop cases. Signed-off-by: Sunny <[email protected]>
1 parent ac80849 commit 010dfc1

File tree

5 files changed

+328
-15
lines changed

5 files changed

+328
-15
lines changed

api/v1beta2/ocirepository_types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ type OCIRepositoryStatus struct {
203203
// +optional
204204
Artifact *Artifact `json:"artifact,omitempty"`
205205

206+
// ContentConfigChecksum is a checksum of all the configurations related to
207+
// the content of the source artifact:
208+
// - .spec.ignore
209+
// - .spec.layerSelector
210+
// observed in .status.observedGeneration version of the object. This can
211+
// be used to determine if the content configuration has changed and the
212+
// artifact needs to be rebuilt.
213+
// It has the format of `<algo>:<checksum>`, for example: `sha256:<checksum>`.
214+
// +optional
215+
ContentConfigChecksum string `json:"contentConfigChecksum,omitempty"`
216+
206217
meta.ReconcileRequestStatus `json:",inline"`
207218
}
208219

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ spec:
300300
- type
301301
type: object
302302
type: array
303+
contentConfigChecksum:
304+
description: 'ContentConfigChecksum is a checksum of all the configurations
305+
related to the content of the source artifact: - .spec.ignore -
306+
.spec.layerSelector observed in .status.observedGeneration version
307+
of the object. This can be used to determine if the content configuration
308+
has changed and the artifact needs to be rebuilt. It has the format
309+
of `<algo>:<checksum>`, for example: `sha256:<checksum>`.'
310+
type: string
303311
lastHandledReconcileAt:
304312
description: LastHandledReconcileAt holds the value of the most recent
305313
reconcile request value, so a change of the annotation value can

controllers/ocirepository_controller.go

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

1919
import (
2020
"context"
21+
"crypto/sha256"
2122
"crypto/tls"
2223
"crypto/x509"
2324
"errors"
@@ -418,8 +419,10 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
418419
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision %s", revision)
419420
}
420421

421-
// Skip pulling if the artifact revision hasn't changes
422-
if obj.GetArtifact().HasRevision(revision) {
422+
// Skip pulling if the artifact revision and the content config checksum has
423+
// not changed.
424+
if obj.GetArtifact().HasRevision(revision) &&
425+
r.calculateContentConfigChecksum(obj) == obj.Status.ContentConfigChecksum {
423426
conditions.Delete(obj, sourcev1.FetchFailedCondition)
424427
return sreconcile.ResultSuccess, nil
425428
}
@@ -922,17 +925,22 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
922925
artifact := r.Storage.NewArtifactFor(obj.Kind, obj, revision,
923926
fmt.Sprintf("%s.tar.gz", r.digestFromRevision(revision)))
924927

928+
// Calculate the content config checksum.
929+
ccc := r.calculateContentConfigChecksum(obj)
930+
925931
// Set the ArtifactInStorageCondition if there's no drift.
926932
defer func() {
927-
if obj.GetArtifact().HasRevision(artifact.Revision) {
933+
if obj.GetArtifact().HasRevision(artifact.Revision) &&
934+
obj.Status.ContentConfigChecksum == ccc {
928935
conditions.Delete(obj, sourcev1.ArtifactOutdatedCondition)
929936
conditions.MarkTrue(obj, sourcev1.ArtifactInStorageCondition, meta.SucceededReason,
930937
"stored artifact for digest '%s'", artifact.Revision)
931938
}
932939
}()
933940

934941
// The artifact is up-to-date
935-
if obj.GetArtifact().HasRevision(artifact.Revision) {
942+
if obj.GetArtifact().HasRevision(artifact.Revision) &&
943+
obj.Status.ContentConfigChecksum == ccc {
936944
r.eventLogf(ctx, obj, events.EventTypeTrace, sourcev1.ArtifactUpToDateReason,
937945
"artifact up-to-date with remote revision: '%s'", artifact.Revision)
938946
return sreconcile.ResultSuccess, nil
@@ -994,9 +1002,10 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
9941002
}
9951003
}
9961004

997-
// Record it on the object
1005+
// Record the observations on the object.
9981006
obj.Status.Artifact = artifact.DeepCopy()
9991007
obj.Status.Artifact.Metadata = metadata.Metadata
1008+
obj.Status.ContentConfigChecksum = ccc
10001009

10011010
// Update symlink on a "best effort" basis
10021011
url, err := r.Storage.Symlink(artifact, "latest.tar.gz")
@@ -1125,3 +1134,21 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
11251134
}
11261135
}
11271136
}
1137+
1138+
// calculateContentConfigChecksum calculates a checksum of all the
1139+
// configurations that result in a change in the source artifact. It can be used
1140+
// to decide if further reconciliation is needed when an artifact already exists
1141+
// for a set of configurations.
1142+
func (r *OCIRepositoryReconciler) calculateContentConfigChecksum(obj *sourcev1.OCIRepository) string {
1143+
c := []byte{}
1144+
// Consider the ignore rules.
1145+
if obj.Spec.Ignore != nil {
1146+
c = append(c, []byte(*obj.Spec.Ignore)...)
1147+
}
1148+
// Consider the layer selector.
1149+
if obj.Spec.LayerSelector != nil {
1150+
c = append(c, []byte(obj.Spec.LayerSelector.MediaType+obj.Spec.LayerSelector.Operation)...)
1151+
}
1152+
1153+
return fmt.Sprintf("sha256:%x", sha256.Sum256(c))
1154+
}

0 commit comments

Comments
 (0)