@@ -18,7 +18,6 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
- "crypto/sha256"
22
21
"crypto/tls"
23
22
"crypto/x509"
24
23
"errors"
@@ -44,6 +43,7 @@ import (
44
43
"k8s.io/apimachinery/pkg/types"
45
44
"k8s.io/apimachinery/pkg/util/sets"
46
45
kuberecorder "k8s.io/client-go/tools/record"
46
+ "k8s.io/utils/pointer"
47
47
48
48
ctrl "sigs.k8s.io/controller-runtime"
49
49
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -427,10 +427,9 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
427
427
conditions .MarkTrue (obj , sourcev1 .SourceVerifiedCondition , meta .SucceededReason , "verified signature of revision %s" , revision )
428
428
}
429
429
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
431
431
// not changed.
432
- if obj .GetArtifact ().HasRevision (revision ) &&
433
- r .calculateContentConfigChecksum (obj ) == obj .Status .ContentConfigChecksum {
432
+ if obj .GetArtifact ().HasRevision (revision ) && ! ociSourceConfigChanged (obj ) {
434
433
conditions .Delete (obj , sourcev1 .FetchFailedCondition )
435
434
return sreconcile .ResultSuccess , nil
436
435
}
@@ -918,22 +917,17 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
918
917
artifact := r .Storage .NewArtifactFor (obj .Kind , obj , revision ,
919
918
fmt .Sprintf ("%s.tar.gz" , r .digestFromRevision (revision )))
920
919
921
- // Calculate the content config checksum.
922
- ccc := r .calculateContentConfigChecksum (obj )
923
-
924
920
// Set the ArtifactInStorageCondition if there's no drift.
925
921
defer func () {
926
- if obj .GetArtifact ().HasRevision (artifact .Revision ) &&
927
- obj .Status .ContentConfigChecksum == ccc {
922
+ if obj .GetArtifact ().HasRevision (artifact .Revision ) && ! ociSourceConfigChanged (obj ) {
928
923
conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
929
924
conditions .MarkTrue (obj , sourcev1 .ArtifactInStorageCondition , meta .SucceededReason ,
930
925
"stored artifact for digest '%s'" , artifact .Revision )
931
926
}
932
927
}()
933
928
934
929
// 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 ) {
937
931
r .eventLogf (ctx , obj , events .EventTypeTrace , sourcev1 .ArtifactUpToDateReason ,
938
932
"artifact up-to-date with remote revision: '%s'" , artifact .Revision )
939
933
return sreconcile .ResultSuccess , nil
@@ -1008,10 +1002,12 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *so
1008
1002
}
1009
1003
}
1010
1004
1011
- // Record it on the object
1005
+ // Record the observations on the object.
1012
1006
obj .Status .Artifact = artifact .DeepCopy ()
1013
1007
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
1015
1011
1016
1012
// Update symlink on a "best effort" basis
1017
1013
url , err := r .Storage .Symlink (artifact , "latest.tar.gz" )
@@ -1141,24 +1137,6 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
1141
1137
}
1142
1138
}
1143
1139
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
-
1162
1140
// craneOptions sets the auth headers, timeout and user agent
1163
1141
// for all operations against remote container registries.
1164
1142
func craneOptions (ctx context.Context , insecure bool ) []crane.Option {
@@ -1208,3 +1186,31 @@ type remoteOptions struct {
1208
1186
craneOpts []crane.Option
1209
1187
verifyOpts []remote.Option
1210
1188
}
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