@@ -18,7 +18,6 @@ package controllers
1818
1919import (
2020 "context"
21- "crypto/sha256"
2221 "crypto/tls"
2322 "crypto/x509"
2423 "errors"
@@ -44,6 +43,7 @@ import (
4443 "k8s.io/apimachinery/pkg/types"
4544 "k8s.io/apimachinery/pkg/util/sets"
4645 kuberecorder "k8s.io/client-go/tools/record"
46+ "k8s.io/utils/pointer"
4747
4848 ctrl "sigs.k8s.io/controller-runtime"
4949 "sigs.k8s.io/controller-runtime/pkg/builder"
@@ -427,10 +427,9 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
427427 conditions .MarkTrue (obj , sourcev1 .SourceVerifiedCondition , meta .SucceededReason , "verified signature of revision %s" , revision )
428428 }
429429
430- // Skip pulling if the artifact revision and the content config checksum has
430+ // Skip pulling if the artifact revision and the source configuration has
431431 // not changed.
432- if obj .GetArtifact ().HasRevision (revision ) &&
433- r .calculateContentConfigChecksum (obj ) == obj .Status .ContentConfigChecksum {
432+ if obj .GetArtifact ().HasRevision (revision ) && ! ociSourceConfigChanged (obj ) {
434433 conditions .Delete (obj , sourcev1 .FetchFailedCondition )
435434 return sreconcile .ResultSuccess , nil
436435 }
@@ -918,22 +917,17 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
918917 artifact := r .Storage .NewArtifactFor (obj .Kind , obj , revision ,
919918 fmt .Sprintf ("%s.tar.gz" , r .digestFromRevision (revision )))
920919
921- // Calculate the content config checksum.
922- ccc := r .calculateContentConfigChecksum (obj )
923-
924920 // Set the ArtifactInStorageCondition if there's no drift.
925921 defer func () {
926- if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
927- obj .Status .ContentConfigChecksum == ccc {
922+ if obj .GetArtifact ().HasRevision (artifact .Revision ) && ! ociSourceConfigChanged (obj ) {
928923 conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
929924 conditions .MarkTrue (obj , sourcev1 .ArtifactInStorageCondition , meta .SucceededReason ,
930925 "stored artifact for digest '%s'" , artifact .Revision )
931926 }
932927 }()
933928
934929 // The artifact is up-to-date
935- if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
936- obj .Status .ContentConfigChecksum == ccc {
930+ if obj .GetArtifact ().HasRevision (artifact .Revision ) && ! ociSourceConfigChanged (obj ) {
937931 r .eventLogf (ctx , obj , events .EventTypeTrace , sourcev1 .ArtifactUpToDateReason ,
938932 "artifact up-to-date with remote revision: '%s'" , artifact .Revision )
939933 return sreconcile .ResultSuccess , nil
@@ -1008,10 +1002,12 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
10081002 }
10091003 }
10101004
1011- // Record it on the object
1005+ // Record the observations on the object.
10121006 obj .Status .Artifact = artifact .DeepCopy ()
10131007 obj .Status .Artifact .Metadata = metadata .Metadata
1014- obj .Status .ContentConfigChecksum = ccc
1008+ obj .Status .ContentConfigChecksum = "" // To be removed in the next API version.
1009+ obj .Status .ObservedIgnore = obj .Spec .Ignore
1010+ obj .Status .ObservedLayerSelector = obj .Spec .LayerSelector
10151011
10161012 // Update symlink on a "best effort" basis
10171013 url , err := r .Storage .Symlink (artifact , "latest.tar.gz" )
@@ -1141,24 +1137,6 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
11411137 }
11421138}
11431139
1144- // calculateContentConfigChecksum calculates a checksum of all the
1145- // configurations that result in a change in the source artifact. It can be used
1146- // to decide if further reconciliation is needed when an artifact already exists
1147- // for a set of configurations.
1148- func (r * OCIRepositoryReconciler ) calculateContentConfigChecksum (obj * sourcev1.OCIRepository ) string {
1149- c := []byte {}
1150- // Consider the ignore rules.
1151- if obj .Spec .Ignore != nil {
1152- c = append (c , []byte (* obj .Spec .Ignore )... )
1153- }
1154- // Consider the layer selector.
1155- if obj .Spec .LayerSelector != nil {
1156- c = append (c , []byte (obj .GetLayerMediaType ()+ obj .GetLayerOperation ())... )
1157- }
1158-
1159- return fmt .Sprintf ("sha256:%x" , sha256 .Sum256 (c ))
1160- }
1161-
11621140// craneOptions sets the auth headers, timeout and user agent
11631141// for all operations against remote container registries.
11641142func craneOptions (ctx context.Context , insecure bool ) []crane.Option {
@@ -1208,3 +1186,31 @@ type remoteOptions struct {
12081186 craneOpts []crane.Option
12091187 verifyOpts []remote.Option
12101188}
1189+
1190+ // ociSourceConfigChanged evaluates the current spec with the observations
1191+ // of the artifact in the status to determine if source configuration has
1192+ // changed and requires rebuilding the artifact.
1193+ func ociSourceConfigChanged (obj * sourcev1.OCIRepository ) bool {
1194+ if ! pointer .StringEqual (obj .Spec .Ignore , obj .Status .ObservedIgnore ) {
1195+ return true
1196+ }
1197+
1198+ if ! layerSelectorEqual (obj .Spec .LayerSelector , obj .Status .ObservedLayerSelector ) {
1199+ return true
1200+ }
1201+
1202+ return false
1203+ }
1204+
1205+ // Returns true if both arguments are nil or both arguments
1206+ // dereference to the same value.
1207+ // Based on k8s.io/utils/pointer/pointer.go pointer value equality.
1208+ func layerSelectorEqual (a , b * sourcev1.OCILayerSelector ) bool {
1209+ if (a == nil ) != (b == nil ) {
1210+ return false
1211+ }
1212+ if a == nil {
1213+ return true
1214+ }
1215+ return * a == * b
1216+ }
0 commit comments