Skip to content

Commit 9ba369d

Browse files
Make cleaner sepeartion between name.Tag and name.Digest paths (WIP)
Signed-off-by: Ilya Dmitrichenko <[email protected]>
1 parent 37cdb71 commit 9ba369d

File tree

1 file changed

+37
-39
lines changed

1 file changed

+37
-39
lines changed

internal/controller/ocirepository_controller.go

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
391391
}
392392

393393
// Get the upstream revision from the artifact digest
394+
// TODO: getRevision resolves the digest, which may change before image is fetched, so it should probaly update ref
394395
revision, err := r.getRevision(ref, opts)
395396
if err != nil {
396397
e := serror.NewGeneric(
@@ -575,33 +576,30 @@ func (r *OCIRepositoryReconciler) selectLayer(obj *ociv1.OCIRepository, image gc
575576
// getRevision fetches the upstream digest, returning the revision in the
576577
// format '<tag>@<digest>'.
577578
func (r *OCIRepositoryReconciler) getRevision(ref name.Reference, options []remote.Option) (string, error) {
578-
repoTag := "" // TODO: can it be obtained from name.Reference directly?
579-
repoName := ref.Context().RepositoryStr()
580-
if s := strings.Split(repoName, ":"); len(s) == 2 && !strings.Contains(repoName, "@") {
581-
repoTag = s[1]
582-
}
583-
584-
if repoTag == "" && !strings.Contains(repoName, "@") {
585-
repoTag = "latest"
586-
}
587-
588-
var digest v1.Hash
589-
desc, err := remote.Head(ref, options...)
590-
if err == nil {
591-
digest = desc.Digest
592-
} else {
593-
rdesc, err := remote.Get(ref, options...)
579+
switch ref := ref.(type) {
580+
case name.Digest:
581+
digest, err := v1.NewHash(ref.DigestStr())
594582
if err != nil {
595583
return "", err
596584
}
597-
digest = rdesc.Descriptor.Digest
598-
}
585+
return digest.String(), nil
586+
case name.Tag:
587+
var digest v1.Hash
599588

600-
revision := digest.String()
601-
if repoTag != "" {
602-
revision = fmt.Sprintf("%s@%s", repoTag, revision)
589+
desc, err := remote.Head(ref, options...)
590+
if err == nil {
591+
digest = desc.Digest
592+
} else {
593+
rdesc, err := remote.Get(ref, options...)
594+
if err != nil {
595+
return "", err
596+
}
597+
digest = rdesc.Descriptor.Digest
598+
}
599+
return fmt.Sprintf("%s@%s", ref.TagStr(), digest.String()), nil
600+
default:
601+
return "", fmt.Errorf("unsupported reference type: %T", ref)
603602
}
604-
return revision, nil
605603
}
606604

607605
// digestFromRevision extracts the digest from the revision string.
@@ -696,53 +694,53 @@ func (r *OCIRepositoryReconciler) verifySignature(ctx context.Context, obj *ociv
696694
}
697695

698696
// parseRepository validates and extracts the repository URL.
699-
func (r *OCIRepositoryReconciler) parseRepository(obj *ociv1.OCIRepository) (name.Reference, error) {
700-
if !strings.HasPrefix(obj.Spec.URL, ociv1.OCIRepositoryPrefix) {
701-
return nil, fmt.Errorf("URL must be in format 'oci://<domain>/<org>/<repo>'")
697+
func (r *OCIRepositoryReconciler) parseRepository(url string) (name.Repository, error) {
698+
if !strings.HasPrefix(url, ociv1.OCIRepositoryPrefix) {
699+
return name.Repository{}, fmt.Errorf("URL must be in format 'oci://<domain>/<org>/<repo>'")
702700
}
703701

704-
url := strings.TrimPrefix(obj.Spec.URL, ociv1.OCIRepositoryPrefix)
705-
ref, err := name.ParseReference(url)
702+
url = strings.TrimPrefix(url, ociv1.OCIRepositoryPrefix)
703+
repo, err := name.NewRepository(url)
706704
if err != nil {
707-
return nil, err
705+
return name.Repository{}, err
708706
}
709707

710-
imageName := strings.TrimPrefix(url, ref.Context().RegistryStr())
708+
imageName := strings.TrimPrefix(url, repo.RegistryStr())
711709
if s := strings.Split(imageName, ":"); len(s) > 1 {
712-
return nil, fmt.Errorf("URL must not contain a tag; remove ':%s'", s[1])
710+
return name.Repository{}, fmt.Errorf("URL must not contain a tag; remove ':%s'", s[1])
713711
}
714712

715-
return ref, nil
713+
return repo, nil
716714
}
717715

718716
// getArtifactRef determines which tag or revision should be used and returns the OCI artifact FQN.
719717
func (r *OCIRepositoryReconciler) getArtifactRef(obj *ociv1.OCIRepository, options []remote.Option) (name.Reference, error) {
720-
ref, err := r.parseRepository(obj)
718+
repo, err := r.parseRepository(obj.Spec.URL)
721719
if err != nil {
722720
return nil, invalidOCIURLError{err}
723721
}
724722

725723
if obj.Spec.Reference != nil {
726724
if obj.Spec.Reference.Digest != "" {
727-
return ref.Context().Digest(fmt.Sprintf("%s@%s", ref, obj.Spec.Reference.Digest)), nil
725+
return repo.Digest(obj.Spec.Reference.Digest), nil
728726
}
729727

730728
if obj.Spec.Reference.SemVer != "" {
731-
return r.getTagBySemver(ref, obj.Spec.Reference.SemVer, options)
729+
return r.getTagBySemver(repo, obj.Spec.Reference.SemVer, options)
732730
}
733731

734732
if obj.Spec.Reference.Tag != "" {
735-
return ref.Context().Tag(obj.Spec.Reference.Tag), nil
733+
return repo.Tag(obj.Spec.Reference.Tag), nil
736734
}
737735
}
738736

739-
return ref, nil
737+
return repo.Tag("latest"), nil
740738
}
741739

742740
// getTagBySemver call the remote container registry, fetches all the tags from the repository,
743741
// and returns the latest tag according to the semver expression.
744-
func (r *OCIRepositoryReconciler) getTagBySemver(ref name.Reference, exp string, options []remote.Option) (name.Reference, error) {
745-
tags, err := remote.List(ref.Context().Repo(), options...)
742+
func (r *OCIRepositoryReconciler) getTagBySemver(repo name.Repository, exp string, options []remote.Option) (name.Reference, error) {
743+
tags, err := remote.List(repo, options...)
746744
if err != nil {
747745
return nil, err
748746
}
@@ -769,7 +767,7 @@ func (r *OCIRepositoryReconciler) getTagBySemver(ref name.Reference, exp string,
769767
}
770768

771769
sort.Sort(sort.Reverse(semver.Collection(matchingVersions)))
772-
return ref.Context().Tag(matchingVersions[0].Original()), nil
770+
return repo.Tag(matchingVersions[0].Original()), nil
773771
}
774772

775773
// keychain generates the credential keychain based on the resource

0 commit comments

Comments
 (0)