@@ -18,6 +18,7 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
+ "crypto/sha256"
21
22
"crypto/tls"
22
23
"crypto/x509"
23
24
"errors"
@@ -418,8 +419,10 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
418
419
conditions .MarkTrue (obj , sourcev1 .SourceVerifiedCondition , meta .SucceededReason , "verified signature of revision %s" , revision )
419
420
}
420
421
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 {
423
426
conditions .Delete (obj , sourcev1 .FetchFailedCondition )
424
427
return sreconcile .ResultSuccess , nil
425
428
}
@@ -922,17 +925,22 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
922
925
artifact := r .Storage .NewArtifactFor (obj .Kind , obj , revision ,
923
926
fmt .Sprintf ("%s.tar.gz" , r .digestFromRevision (revision )))
924
927
928
+ // Calculate the content config checksum.
929
+ ccc := r .calculateContentConfigChecksum (obj )
930
+
925
931
// Set the ArtifactInStorageCondition if there's no drift.
926
932
defer func () {
927
- if obj .GetArtifact ().HasRevision (artifact .Revision ) {
933
+ if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
934
+ obj .Status .ContentConfigChecksum == ccc {
928
935
conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
929
936
conditions .MarkTrue (obj , sourcev1 .ArtifactInStorageCondition , meta .SucceededReason ,
930
937
"stored artifact for digest '%s'" , artifact .Revision )
931
938
}
932
939
}()
933
940
934
941
// 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 {
936
944
r .eventLogf (ctx , obj , events .EventTypeTrace , sourcev1 .ArtifactUpToDateReason ,
937
945
"artifact up-to-date with remote revision: '%s'" , artifact .Revision )
938
946
return sreconcile .ResultSuccess , nil
@@ -994,9 +1002,10 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
994
1002
}
995
1003
}
996
1004
997
- // Record it on the object
1005
+ // Record the observations on the object.
998
1006
obj .Status .Artifact = artifact .DeepCopy ()
999
1007
obj .Status .Artifact .Metadata = metadata .Metadata
1008
+ obj .Status .ContentConfigChecksum = ccc
1000
1009
1001
1010
// Update symlink on a "best effort" basis
1002
1011
url , err := r .Storage .Symlink (artifact , "latest.tar.gz" )
@@ -1125,3 +1134,21 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
1125
1134
}
1126
1135
}
1127
1136
}
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