controllers: make OCIRepository compat with RFC-0005
Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
parent
909ece4092
commit
469c9387ee
|
@ -22,6 +22,7 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/fluxcd/pkg/git"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -390,7 +391,7 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
|
||||||
return sreconcile.ResultEmpty, e
|
return sreconcile.ResultEmpty, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the upstream revision from the artifact digest
|
// Get the upstream revision from the artifact revision
|
||||||
revision, err := r.getRevision(url, opts.craneOpts)
|
revision, err := r.getRevision(url, opts.craneOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := serror.NewGeneric(
|
e := serror.NewGeneric(
|
||||||
|
@ -405,7 +406,7 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
|
||||||
|
|
||||||
// Mark observations about the revision on the object
|
// Mark observations about the revision on the object
|
||||||
defer func() {
|
defer func() {
|
||||||
if !obj.GetArtifact().HasRevision(revision) {
|
if obj.GetArtifact() == nil || git.TransformRevision(obj.GetArtifact().Revision) != git.TransformRevision(revision) {
|
||||||
message := fmt.Sprintf("new revision '%s' for '%s'", revision, url)
|
message := fmt.Sprintf("new revision '%s' for '%s'", revision, url)
|
||||||
if obj.GetArtifact() != nil {
|
if obj.GetArtifact() != nil {
|
||||||
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", message)
|
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", message)
|
||||||
|
@ -425,7 +426,7 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
|
||||||
if obj.Spec.Verify == nil {
|
if obj.Spec.Verify == nil {
|
||||||
// Remove old observations if verification was disabled
|
// Remove old observations if verification was disabled
|
||||||
conditions.Delete(obj, sourcev1.SourceVerifiedCondition)
|
conditions.Delete(obj, sourcev1.SourceVerifiedCondition)
|
||||||
} else if !obj.GetArtifact().HasRevision(revision) ||
|
} else if (obj.GetArtifact() == nil || git.TransformRevision(obj.GetArtifact().Revision) != git.TransformRevision(revision)) ||
|
||||||
conditions.GetObservedGeneration(obj, sourcev1.SourceVerifiedCondition) != obj.Generation ||
|
conditions.GetObservedGeneration(obj, sourcev1.SourceVerifiedCondition) != obj.Generation ||
|
||||||
conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
|
conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
|
||||||
|
|
||||||
|
@ -458,7 +459,9 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
|
||||||
|
|
||||||
// Skip pulling if the artifact revision and the source configuration has
|
// Skip pulling if the artifact revision and the source configuration has
|
||||||
// not changed.
|
// not changed.
|
||||||
if obj.GetArtifact().HasRevision(revision) && !ociContentConfigChanged(obj) {
|
if (obj.GetArtifact() != nil &&
|
||||||
|
git.TransformRevision(obj.GetArtifact().Revision) == git.TransformRevision(revision)) &&
|
||||||
|
!ociContentConfigChanged(obj) {
|
||||||
conditions.Delete(obj, sourcev1.FetchFailedCondition)
|
conditions.Delete(obj, sourcev1.FetchFailedCondition)
|
||||||
return sreconcile.ResultSuccess, nil
|
return sreconcile.ResultSuccess, nil
|
||||||
}
|
}
|
||||||
|
@ -582,7 +585,7 @@ func (r *OCIRepositoryReconciler) selectLayer(obj *sourcev1.OCIRepository, image
|
||||||
return blob, nil
|
return blob, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRevision fetches the upstream digest and returns the revision in the format `<tag>/<digest>`
|
// getRevision fetches the upstream revision and returns the revision in the format `<tag>/<revision>`
|
||||||
func (r *OCIRepositoryReconciler) getRevision(url string, options []crane.Option) (string, error) {
|
func (r *OCIRepositoryReconciler) getRevision(url string, options []crane.Option) (string, error) {
|
||||||
ref, err := name.ParseReference(url)
|
ref, err := name.ParseReference(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -609,16 +612,16 @@ func (r *OCIRepositoryReconciler) getRevision(url string, options []crane.Option
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
revision := digestHash.Hex
|
revision := digestHash.String()
|
||||||
if repoTag != "" {
|
if repoTag != "" {
|
||||||
revision = fmt.Sprintf("%s/%s", repoTag, digestHash.Hex)
|
revision = fmt.Sprintf("%s@%s", repoTag, revision)
|
||||||
}
|
}
|
||||||
return revision, nil
|
return revision, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// digestFromRevision extract the digest from the revision string
|
// digestFromRevision extract the revision from the revision string
|
||||||
func (r *OCIRepositoryReconciler) digestFromRevision(revision string) string {
|
func (r *OCIRepositoryReconciler) digestFromRevision(revision string) string {
|
||||||
parts := strings.Split(revision, "/")
|
parts := strings.Split(revision, "@")
|
||||||
return parts[len(parts)-1]
|
return parts[len(parts)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +725,7 @@ func (r *OCIRepositoryReconciler) parseRepositoryURL(obj *sourcev1.OCIRepository
|
||||||
return ref.Context().Name(), nil
|
return ref.Context().Name(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getArtifactURL determines which tag or digest should be used and returns the OCI artifact FQN.
|
// getArtifactURL determines which tag or revision should be used and returns the OCI artifact FQN.
|
||||||
func (r *OCIRepositoryReconciler) getArtifactURL(obj *sourcev1.OCIRepository, options []crane.Option) (string, error) {
|
func (r *OCIRepositoryReconciler) getArtifactURL(obj *sourcev1.OCIRepository, options []crane.Option) (string, error) {
|
||||||
url, err := r.parseRepositoryURL(obj)
|
url, err := r.parseRepositoryURL(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -967,7 +970,9 @@ func (r *OCIRepositoryReconciler) reconcileArtifact(ctx context.Context, sp *pat
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// The artifact is up-to-date
|
// The artifact is up-to-date
|
||||||
if obj.GetArtifact().HasRevision(artifact.Revision) && !ociContentConfigChanged(obj) {
|
if (obj.GetArtifact() != nil &&
|
||||||
|
git.TransformRevision(obj.GetArtifact().Revision) == git.TransformRevision(revision)) &&
|
||||||
|
!ociContentConfigChanged(obj) {
|
||||||
r.eventLogf(ctx, obj, eventv1.EventTypeTrace, sourcev1.ArtifactUpToDateReason,
|
r.eventLogf(ctx, obj, eventv1.EventTypeTrace, sourcev1.ArtifactUpToDateReason,
|
||||||
"artifact up-to-date with remote revision: '%s'", artifact.Revision)
|
"artifact up-to-date with remote revision: '%s'", artifact.Revision)
|
||||||
return sreconcile.ResultSuccess, nil
|
return sreconcile.ResultSuccess, nil
|
||||||
|
@ -1141,7 +1146,7 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, oldObj, newObj *so
|
||||||
fmt.Sprintf("%s/%s", sourcev1.GroupVersion.Group, eventv1.MetaChecksumKey): newObj.Status.Artifact.Checksum,
|
fmt.Sprintf("%s/%s", sourcev1.GroupVersion.Group, eventv1.MetaChecksumKey): newObj.Status.Artifact.Checksum,
|
||||||
}
|
}
|
||||||
if newObj.Status.Artifact.Digest != "" {
|
if newObj.Status.Artifact.Digest != "" {
|
||||||
annotations[sourcev1.GroupVersion.Group+"/digest"] = newObj.Status.Artifact.Digest
|
annotations[sourcev1.GroupVersion.Group+"/revision"] = newObj.Status.Artifact.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldChecksum string
|
var oldChecksum string
|
||||||
|
|
|
@ -86,7 +86,7 @@ func TestOCIRepository_Reconcile(t *testing.T) {
|
||||||
url string
|
url string
|
||||||
tag string
|
tag string
|
||||||
semver string
|
semver string
|
||||||
digest string
|
revision string
|
||||||
mediaType string
|
mediaType string
|
||||||
operation string
|
operation string
|
||||||
assertArtifact []artifactFixture
|
assertArtifact []artifactFixture
|
||||||
|
@ -95,7 +95,7 @@ func TestOCIRepository_Reconcile(t *testing.T) {
|
||||||
name: "public tag",
|
name: "public tag",
|
||||||
url: podinfoVersions["6.1.6"].url,
|
url: podinfoVersions["6.1.6"].url,
|
||||||
tag: podinfoVersions["6.1.6"].tag,
|
tag: podinfoVersions["6.1.6"].tag,
|
||||||
digest: fmt.Sprintf("%s/%s", podinfoVersions["6.1.6"].tag, podinfoVersions["6.1.6"].digest.Hex),
|
revision: fmt.Sprintf("%s@%s", podinfoVersions["6.1.6"].tag, podinfoVersions["6.1.6"].digest.String()),
|
||||||
mediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
mediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
operation: sourcev1.OCILayerCopy,
|
operation: sourcev1.OCILayerCopy,
|
||||||
assertArtifact: []artifactFixture{
|
assertArtifact: []artifactFixture{
|
||||||
|
@ -110,10 +110,10 @@ func TestOCIRepository_Reconcile(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "public semver",
|
name: "public semver",
|
||||||
url: podinfoVersions["6.1.5"].url,
|
url: podinfoVersions["6.1.5"].url,
|
||||||
semver: ">= 6.1 <= 6.1.5",
|
semver: ">= 6.1 <= 6.1.5",
|
||||||
digest: fmt.Sprintf("%s/%s", podinfoVersions["6.1.5"].tag, podinfoVersions["6.1.5"].digest.Hex),
|
revision: fmt.Sprintf("%s@%s", podinfoVersions["6.1.5"].tag, podinfoVersions["6.1.5"].digest.String()),
|
||||||
assertArtifact: []artifactFixture{
|
assertArtifact: []artifactFixture{
|
||||||
{
|
{
|
||||||
expectedPath: "kustomize/deployment.yaml",
|
expectedPath: "kustomize/deployment.yaml",
|
||||||
|
@ -177,8 +177,8 @@ func TestOCIRepository_Reconcile(t *testing.T) {
|
||||||
// Wait for the object to be Ready
|
// Wait for the object to be Ready
|
||||||
waitForSourceReadyWithArtifact(ctx, g, obj)
|
waitForSourceReadyWithArtifact(ctx, g, obj)
|
||||||
|
|
||||||
// Check if the revision matches the expected digest
|
// Check if the revision matches the expected revision
|
||||||
g.Expect(obj.Status.Artifact.Revision).To(Equal(tt.digest))
|
g.Expect(obj.Status.Artifact.Revision).To(Equal(tt.revision))
|
||||||
|
|
||||||
// Check if the metadata matches the expected annotations
|
// Check if the metadata matches the expected annotations
|
||||||
g.Expect(obj.Status.Artifact.Metadata[oci.SourceAnnotation]).To(ContainSubstring("podinfo"))
|
g.Expect(obj.Status.Artifact.Metadata[oci.SourceAnnotation]).To(ContainSubstring("podinfo"))
|
||||||
|
@ -293,7 +293,6 @@ func TestOCIRepository_Reconcile_MediaType(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
||||||
g := NewWithT(t)
|
g := NewWithT(t)
|
||||||
|
|
||||||
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-mediatype-test")
|
ns, err := testEnv.CreateNamespace(ctx, "ocirepository-mediatype-test")
|
||||||
|
@ -383,8 +382,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
name: "HTTP without basic auth",
|
name: "HTTP without basic auth",
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -404,8 +403,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
includeSecret: true,
|
includeSecret: true,
|
||||||
},
|
},
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -425,8 +424,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
includeSA: true,
|
includeSA: true,
|
||||||
},
|
},
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -508,8 +507,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -580,8 +579,8 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
},
|
},
|
||||||
provider: "azure",
|
provider: "azure",
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -678,7 +677,7 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
|
||||||
|
|
||||||
assertConditions := tt.assertConditions
|
assertConditions := tt.assertConditions
|
||||||
for k := range assertConditions {
|
for k := range assertConditions {
|
||||||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<digest>", fmt.Sprintf("%s/%s", img.tag, img.digest.Hex))
|
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<revision>", fmt.Sprintf("%s@%s", img.tag, img.digest.String()))
|
||||||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<url>", repoURL)
|
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<url>", repoURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,7 +749,7 @@ func TestOCIRepository_CertSecret(t *testing.T) {
|
||||||
digest: pi.digest,
|
digest: pi.digest,
|
||||||
certSecret: &tlsSecretClientCert,
|
certSecret: &tlsSecretClientCert,
|
||||||
expectreadyconition: true,
|
expectreadyconition: true,
|
||||||
expectedstatusmessage: fmt.Sprintf("stored artifact for digest '%s'", pi.digest.Hex),
|
expectedstatusmessage: fmt.Sprintf("stored artifact for digest '%s'", pi.digest.String()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "test connection with no secret",
|
name: "test connection with no secret",
|
||||||
|
@ -874,7 +873,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "no reference (latest tag)",
|
name: "no reference (latest tag)",
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
wantRevision: fmt.Sprintf("latest/%s", img6.digest.Hex),
|
wantRevision: fmt.Sprintf("latest@%s", img6.digest.String()),
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -886,7 +885,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
Tag: "6.1.6",
|
Tag: "6.1.6",
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
wantRevision: fmt.Sprintf("%s/%s", img6.tag, img6.digest.Hex),
|
wantRevision: fmt.Sprintf("%s@%s", img6.tag, img6.digest.String()),
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -898,7 +897,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
SemVer: ">= 6.1.5",
|
SemVer: ">= 6.1.5",
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
wantRevision: fmt.Sprintf("%s/%s", img6.tag, img6.digest.Hex),
|
wantRevision: fmt.Sprintf("%s@%s", img6.tag, img6.digest.String()),
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -909,7 +908,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Digest: img6.digest.String(),
|
Digest: img6.digest.String(),
|
||||||
},
|
},
|
||||||
wantRevision: img6.digest.Hex,
|
wantRevision: img6.digest.String(),
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -956,7 +955,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
Tag: "6.1.5",
|
Tag: "6.1.5",
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
wantRevision: fmt.Sprintf("%s/%s", img6.tag, img6.digest.Hex),
|
wantRevision: fmt.Sprintf("%s@%s", img6.tag, img6.digest.String()),
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -970,7 +969,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
|
||||||
Digest: img5.digest.String(),
|
Digest: img5.digest.String(),
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
wantRevision: img5.digest.Hex,
|
wantRevision: img5.digest.String(),
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision"),
|
||||||
|
@ -1058,13 +1057,13 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Tag: "6.1.4",
|
Tag: "6.1.4",
|
||||||
},
|
},
|
||||||
digest: img4.digest.Hex,
|
digest: img4.digest.String(),
|
||||||
shouldSign: true,
|
shouldSign: true,
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision <digest>"),
|
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision <revision>"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1072,13 +1071,13 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Tag: "6.1.5",
|
Tag: "6.1.5",
|
||||||
},
|
},
|
||||||
digest: img5.digest.Hex,
|
digest: img5.digest.String(),
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
wantErrMsg: "failed to verify the signature using provider 'cosign': no matching signatures were found for '<url>'",
|
wantErrMsg: "failed to verify the signature using provider 'cosign': no matching signatures were found for '<url>'",
|
||||||
want: sreconcile.ResultEmpty,
|
want: sreconcile.ResultEmpty,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider>': no matching signatures were found for '<url>'"),
|
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider>': no matching signatures were found for '<url>'"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1087,34 +1086,34 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Tag: "6.1.5",
|
Tag: "6.1.5",
|
||||||
},
|
},
|
||||||
digest: img5.digest.Hex,
|
digest: img5.digest.String(),
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
want: sreconcile.ResultEmpty,
|
want: sreconcile.ResultEmpty,
|
||||||
keyless: true,
|
keyless: true,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no matching signatures"),
|
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no matching signatures"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "verify failed before, removed from spec, remove condition",
|
name: "verify failed before, removed from spec, remove condition",
|
||||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||||
digest: img4.digest.Hex,
|
digest: img4.digest.String(),
|
||||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, "VerifyFailed", "fail msg")
|
conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, "VerifyFailed", "fail msg")
|
||||||
obj.Spec.Verify = nil
|
obj.Spec.Verify = nil
|
||||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s/%s", img4.tag, img4.digest.Hex)}
|
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())}
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "same artifact, verified before, change in obj gen verify again",
|
name: "same artifact, verified before, change in obj gen verify again",
|
||||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||||
digest: img4.digest.Hex,
|
digest: img4.digest.String(),
|
||||||
shouldSign: true,
|
shouldSign: true,
|
||||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s/%s", img4.tag, img4.digest.Hex)}
|
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())}
|
||||||
// Set Verified with old observed generation and different reason/message.
|
// Set Verified with old observed generation and different reason/message.
|
||||||
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
||||||
// Set new object generation.
|
// Set new object generation.
|
||||||
|
@ -1122,17 +1121,17 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision <digest>"),
|
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of revision <revision>"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no verify for already verified, verified condition remains the same",
|
name: "no verify for already verified, verified condition remains the same",
|
||||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||||
digest: img4.digest.Hex,
|
digest: img4.digest.String(),
|
||||||
shouldSign: true,
|
shouldSign: true,
|
||||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
// Artifact present and custom verified condition reason/message.
|
// Artifact present and custom verified condition reason/message.
|
||||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s/%s", img4.tag, img4.digest.Hex)}
|
obj.Status.Artifact = &sourcev1.Artifact{Revision: fmt.Sprintf("%s@%s", img4.tag, img4.digest.String())}
|
||||||
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
||||||
},
|
},
|
||||||
want: sreconcile.ResultSuccess,
|
want: sreconcile.ResultSuccess,
|
||||||
|
@ -1145,14 +1144,14 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Tag: "6.1.4",
|
Tag: "6.1.4",
|
||||||
},
|
},
|
||||||
digest: img4.digest.Hex,
|
digest: img4.digest.String(),
|
||||||
shouldSign: true,
|
shouldSign: true,
|
||||||
insecure: true,
|
insecure: true,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
want: sreconcile.ResultEmpty,
|
want: sreconcile.ResultEmpty,
|
||||||
assertConditions: []metav1.Condition{
|
assertConditions: []metav1.Condition{
|
||||||
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<digest>' for '<url>'"),
|
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
|
||||||
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "cosign does not support insecure registries"),
|
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "cosign does not support insecure registries"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1248,7 +1247,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
|
|
||||||
assertConditions := tt.assertConditions
|
assertConditions := tt.assertConditions
|
||||||
for k := range assertConditions {
|
for k := range assertConditions {
|
||||||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<digest>", fmt.Sprintf("%s/%s", tt.reference.Tag, tt.digest))
|
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<revision>", fmt.Sprintf("%s@%s", tt.reference.Tag, tt.digest))
|
||||||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<url>", artifactURL)
|
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<url>", artifactURL)
|
||||||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<provider>", "cosign")
|
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<provider>", "cosign")
|
||||||
}
|
}
|
||||||
|
@ -1282,7 +1281,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
||||||
func TestOCIRepository_reconcileSource_noop(t *testing.T) {
|
func TestOCIRepository_reconcileSource_noop(t *testing.T) {
|
||||||
g := NewWithT(t)
|
g := NewWithT(t)
|
||||||
|
|
||||||
testRevision := "6.1.5/d1fc4595915714af2492dc4b66097de1e10f80150c8899907d8f8e61c6d6f67d"
|
testRevision := "6.1.5@sha256:8a0eed109e056ab1f7e70e8fb47e00cf6f560ca5cd910c83451882e07edb77fa"
|
||||||
|
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
server, err := setupRegistryServer(ctx, tmpDir, registryOptions{})
|
server, err := setupRegistryServer(ctx, tmpDir, registryOptions{})
|
||||||
|
@ -1316,6 +1315,28 @@ func TestOCIRepository_reconcileSource_noop(t *testing.T) {
|
||||||
g.Expect(artifact.Metadata).To(BeEmpty())
|
g.Expect(artifact.Metadata).To(BeEmpty())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "noop - artifact revisions match (legacy)",
|
||||||
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
|
obj.Status.Artifact = &sourcev1.Artifact{
|
||||||
|
Revision: "6.1.5/8a0eed109e056ab1f7e70e8fb47e00cf6f560ca5cd910c83451882e07edb77fa",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
afterFunc: func(g *WithT, artifact *sourcev1.Artifact) {
|
||||||
|
g.Expect(artifact.Metadata).To(BeEmpty())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "noop - artifact revisions match (legacy: digest)",
|
||||||
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
|
obj.Status.Artifact = &sourcev1.Artifact{
|
||||||
|
Revision: "8a0eed109e056ab1f7e70e8fb47e00cf6f560ca5cd910c83451882e07edb77fa",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
afterFunc: func(g *WithT, artifact *sourcev1.Artifact) {
|
||||||
|
g.Expect(artifact.Metadata).To(BeEmpty())
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "full reconcile - same rev, unobserved ignore",
|
name: "full reconcile - same rev, unobserved ignore",
|
||||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||||
|
@ -1723,9 +1744,9 @@ func TestOCIRepository_getArtifactURL(t *testing.T) {
|
||||||
name: "valid url with digest reference",
|
name: "valid url with digest reference",
|
||||||
url: "oci://ghcr.io/stefanprodan/charts",
|
url: "oci://ghcr.io/stefanprodan/charts",
|
||||||
reference: &sourcev1.OCIRepositoryRef{
|
reference: &sourcev1.OCIRepositoryRef{
|
||||||
Digest: imgs["6.1.6"].digest.Hex,
|
Digest: imgs["6.1.6"].digest.String(),
|
||||||
},
|
},
|
||||||
want: "ghcr.io/stefanprodan/charts@" + imgs["6.1.6"].digest.Hex,
|
want: "ghcr.io/stefanprodan/charts@" + imgs["6.1.6"].digest.String(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "valid url with semver reference",
|
name: "valid url with semver reference",
|
||||||
|
@ -2236,7 +2257,7 @@ func pushMultiplePodinfoImages(serverURL string, versions ...string) (map[string
|
||||||
func setPodinfoImageAnnotations(img gcrv1.Image, tag string) gcrv1.Image {
|
func setPodinfoImageAnnotations(img gcrv1.Image, tag string) gcrv1.Image {
|
||||||
metadata := map[string]string{
|
metadata := map[string]string{
|
||||||
oci.SourceAnnotation: "https://github.com/stefanprodan/podinfo",
|
oci.SourceAnnotation: "https://github.com/stefanprodan/podinfo",
|
||||||
oci.RevisionAnnotation: fmt.Sprintf("%s/SHA", tag),
|
oci.RevisionAnnotation: fmt.Sprintf("%s@sha256:8a0eed109e056ab1f7e70e8fb47e00cf6f560ca5cd910c83451882e07edb77fa", tag),
|
||||||
}
|
}
|
||||||
return mutate.Annotations(img, metadata).(gcrv1.Image)
|
return mutate.Annotations(img, metadata).(gcrv1.Image)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue