Skip to content

Commit

Permalink
handle implicit version part of an artifact identity
Browse files Browse the repository at this point in the history
  • Loading branch information
mandelsoft committed Oct 31, 2024
1 parent a60c79f commit 77f98d6
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 121 deletions.
16 changes: 16 additions & 0 deletions api/helper/builder/ocm_identity.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package builder

import (
metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
)

const T_OCMMETA = "element with metadata"

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -10,6 +14,18 @@ func (b *Builder) ExtraIdentity(name string, value string) {
b.ocm_meta.ExtraIdentity.Set(name, value)
}

func (b *Builder) ExtraIdentities(extras ...string) {
b.expect(b.ocm_meta, T_OCMMETA)

id := metav1.NewExtraIdentity(extras...)
if b.ocm_meta.ExtraIdentity == nil {
b.ocm_meta.ExtraIdentity = metav1.Identity{}
}
for k, v := range id {
b.ocm_meta.ExtraIdentity.Set(k, v)
}
}

////////////////////////////////////////////////////////////////////////////////

func (b *Builder) RemoveExtraIdentity(name string) {
Expand Down
6 changes: 3 additions & 3 deletions api/oci/art_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ var _ = Describe("art parsing", func() {
It("succeeds", func() {
CheckArt("ubuntu", &oci.ArtSpec{Repository: "ubuntu"})
CheckArt("ubuntu/test", &oci.ArtSpec{Repository: "ubuntu/test"})
CheckArt("ubuntu/test@"+digest.String(), &oci.ArtSpec{Repository: "ubuntu/test", Digest: &digest})
CheckArt("ubuntu/test:"+tag, &oci.ArtSpec{Repository: "ubuntu/test", Tag: &tag})
CheckArt("ubuntu/test:"+tag+"@"+digest.String(), &oci.ArtSpec{Repository: "ubuntu/test", Digest: &digest, Tag: &tag})
CheckArt("ubuntu/test@"+digest.String(), &oci.ArtSpec{Repository: "ubuntu/test", ArtVersion: oci.ArtVersion{Digest: &digest}})
CheckArt("ubuntu/test:"+tag, &oci.ArtSpec{Repository: "ubuntu/test", ArtVersion: oci.ArtVersion{Tag: &tag}})
CheckArt("ubuntu/test:"+tag+"@"+digest.String(), &oci.ArtSpec{Repository: "ubuntu/test", ArtVersion: oci.ArtVersion{Digest: &digest, Tag: &tag}})
})

It("fails", func() {
Expand Down
10 changes: 8 additions & 2 deletions api/oci/extensions/repositories/artifactset/utils_synthesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"ocm.software/ocm/api/oci/artdesc"
"ocm.software/ocm/api/oci/cpi"
"ocm.software/ocm/api/oci/ociutils"
"ocm.software/ocm/api/oci/tools/transfer"
"ocm.software/ocm/api/oci/tools/transfer/filters"
"ocm.software/ocm/api/utils/accessio"
Expand Down Expand Up @@ -92,14 +93,19 @@ func SynthesizeArtifactBlobForArtifact(art cpi.ArtifactAccess, ref string, filte
return nil, err
}

vers, err := ociutils.ParseVersion(ref)
if err != nil {
return nil, err
}

return SythesizeArtifactSet(func(set *ArtifactSet) (string, error) {
dig, err := transfer.TransferArtifactWithFilter(art, set, filters.And(filter...))
if err != nil {
return "", fmt.Errorf("failed to transfer artifact: %w", err)
}

if ok, _ := artdesc.IsDigest(ref); !ok {
err = set.AddTags(*dig, ref)
if ok := vers.IsTagged(); ok {
err = set.AddTags(*dig, vers.GetTag())
if err != nil {
return "", fmt.Errorf("failed to add tag: %w", err)
}
Expand Down
83 changes: 83 additions & 0 deletions api/oci/ociutils/ref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package ociutils

import (
"strings"

"github.com/mandelsoft/goutils/generics"
"github.com/opencontainers/go-digest"
)

// ParseVersion parses the version part of an OCI reference consisting
// of an optional tag and/or digest.
func ParseVersion(vers string) (ArtVersion, error) {
if strings.HasPrefix(vers, "@") {
dig, err := digest.Parse(vers[1:])
if err != nil {
return ArtVersion{}, err
}
return ArtVersion{
Tag: nil,
Digest: &dig,
}, nil
}

i := strings.Index(vers, "@")
if i > 0 {
dig, err := digest.Parse(vers[i+1:])
if err != nil {
return ArtVersion{}, err
}
return ArtVersion{
Tag: generics.Pointer(vers[:i]),
Digest: &dig,
}, nil
}
return ArtVersion{
Tag: &vers,
}, nil
}

// ArtVersion is the version part of an OCI reference consisting of an
// optional tag and/or digest. Both parts may be nil, if a reference
// does not include a version part.
type ArtVersion struct {
// +optional
Tag *string `json:"tag,omitempty"`
// +optional
Digest *digest.Digest `json:"digest,omitempty"`
}

func (v *ArtVersion) VersionSpec() string {
vers := ""
if v != nil {
if v.Tag != nil {
vers = *v.Tag
}
if v.Digest != nil {
vers += "@" + string(*v.Digest)
}
if vers == "" {
return "latest"
}
}
return vers
}

func (v *ArtVersion) IsVersion() bool {
return v.Tag != nil || v.Digest != nil
}

func (v *ArtVersion) IsTagged() bool {
return v.Tag != nil
}

func (v *ArtVersion) IsDigested() bool {
return v.Digest != nil
}

func (v *ArtVersion) GetTag() string {
if v.Tag != nil {
return *v.Tag
}
return ""
}
34 changes: 13 additions & 21 deletions api/oci/ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/opencontainers/go-digest"

"ocm.software/ocm/api/oci/grammar"
"ocm.software/ocm/api/oci/ociutils"
)

// to find a suitable secret for images on Docker Hub, we need its two domains to do matching.
Expand Down Expand Up @@ -224,6 +225,10 @@ func (r RefSpec) DeepCopy() RefSpec {

////////////////////////////////////////////////////////////////////////////////

func ParseVersion(vers string) (ArtVersion, error) {
return ociutils.ParseVersion(vers)
}

func ParseArt(art string) (ArtSpec, error) {
match := grammar.AnchoredArtifactVersionRegexp.FindSubmatch([]byte(art))

Expand All @@ -247,19 +252,21 @@ func ParseArt(art string) (ArtSpec, error) {
}
return ArtSpec{
Repository: string(match[1]),
Tag: tag,
Digest: dig,
ArtVersion: ArtVersion{
Tag: tag,
Digest: dig,
},
}, nil
}

type ArtVersion = ociutils.ArtVersion

// ArtSpec is a go internal representation of a oci reference.
type ArtSpec struct {
// Repository is the part of a reference without its hostname
Repository string `json:"repository"`
// +optional
Tag *string `json:"tag,omitempty"`
// +optional
Digest *digest.Digest `json:"digest,omitempty"`
// artifact version
ArtVersion `json:",inline"`
}

func (r *ArtSpec) Version() string {
Expand All @@ -276,21 +283,6 @@ func (r *ArtSpec) IsRegistry() bool {
return r.Repository == ""
}

func (r *ArtSpec) IsVersion() bool {
return r.Tag != nil || r.Digest != nil
}

func (r *ArtSpec) IsTagged() bool {
return r.Tag != nil
}

func (r *ArtSpec) GetTag() string {
if r.Tag != nil {
return *r.Tag
}
return ""
}

func (r *ArtSpec) String() string {
s := r.Repository
if r.Tag != nil {
Expand Down
Loading

0 comments on commit 77f98d6

Please sign in to comment.