Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

access method ocm #896

Merged
merged 9 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/config/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anchore
api
archlinux
artifactid
attr
aur
auth
autoconfigure
Expand Down
8 changes: 4 additions & 4 deletions api/oci/extensions/repositories/ctf/ctf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ var _ = Describe("ctf management", func() {
})

It("instantiate filesystem ctf", func() {
r, err := spec.Repository(nil, nil)
r, err := spec.Repository(cpi.DefaultContext(), nil)
Expect(err).To(Succeed())
Expect(vfs.DirExists(tempfs, "test/"+ctf.BlobsDirectoryName)).To(BeTrue())

Expand All @@ -111,7 +111,7 @@ var _ = Describe("ctf management", func() {
It("instantiate tgz artifact", func() {
ctf.FormatTGZ.ApplyOption(&spec.StandardOptions)
spec.FilePath = "test.tgz"
r, err := spec.Repository(nil, nil)
r, err := spec.Repository(cpi.DefaultContext(), nil)
Expect(err).To(Succeed())

n, err := r.LookupNamespace("mandelsoft/test")
Expand Down Expand Up @@ -156,7 +156,7 @@ var _ = Describe("ctf management", func() {

Context("manifest", func() {
It("read from filesystem ctf", func() {
r, err := spec.Repository(nil, nil)
r, err := spec.Repository(cpi.DefaultContext(), nil)
Expect(err).To(Succeed())
Expect(vfs.DirExists(tempfs, "test/"+ctf.BlobsDirectoryName)).To(BeTrue())
n, err := r.LookupNamespace("mandelsoft/test")
Expand All @@ -165,7 +165,7 @@ var _ = Describe("ctf management", func() {
Expect(n.Close()).To(Succeed())
Expect(r.Close()).To(Succeed())

r, err = ctf.Open(nil, accessobj.ACC_READONLY, "test", 0, accessio.PathFileSystem(tempfs))
r, err = ctf.Open(cpi.DefaultContext(), accessobj.ACC_READONLY, "test", 0, accessio.PathFileSystem(tempfs))
Expect(err).To(Succeed())
defer r.Close()

Expand Down
9 changes: 7 additions & 2 deletions api/oci/extensions/repositories/ctf/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/mandelsoft/goutils/errors"
"github.com/mandelsoft/vfs/pkg/vfs"

"ocm.software/ocm/api/datacontext/attrs/vfsattr"
"ocm.software/ocm/api/oci/cpi"
"ocm.software/ocm/api/oci/extensions/repositories/ctf/format"
"ocm.software/ocm/api/oci/extensions/repositories/ctf/index"
Expand Down Expand Up @@ -126,8 +127,12 @@ func OpenFromBlob(ctx cpi.ContextProvider, acc accessobj.AccessMode, blob blobac
return Open(ctx, acc&accessobj.ACC_READONLY, "", 0, o)
}

func Open(ctx cpi.ContextProvider, acc accessobj.AccessMode, path string, mode vfs.FileMode, opts ...accessio.Option) (*Object, error) {
o, create, err := accessobj.HandleAccessMode(acc, path, nil, opts...)
func Open(ctx cpi.ContextProvider, acc accessobj.AccessMode, path string, mode vfs.FileMode, olist ...accessio.Option) (*Object, error) {
opts, err := accessio.AccessOptions(&accessio.StandardOptions{PathFileSystem: vfsattr.Get(ctx.OCIContext())}, olist...)
if err != nil {
return nil, err
}
o, create, err := accessobj.HandleAccessMode(acc, path, opts)
if err != nil {
return nil, err
}
Expand Down
5 changes: 4 additions & 1 deletion api/oci/extensions/repositories/ctf/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ func (s *RepositorySpec) UniformRepositorySpec() *cpi.UniformRepositorySpec {
}

func (a *RepositorySpec) Repository(ctx cpi.Context, creds credentials.Credentials) (cpi.Repository, error) {
return Open(ctx, a.AccessMode, a.FilePath, 0o700, &a.StandardOptions)
opts := a.StandardOptions
opts.Default(vfsattr.Get(ctx))

return Open(ctx, a.AccessMode, a.FilePath, 0o700, &opts)
}

func (a *RepositorySpec) Validate(ctx cpi.Context, creds credentials.Credentials, context ...credentials.UsageContext) error {
Expand Down
5 changes: 5 additions & 0 deletions api/ocm/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import (
"ocm.software/ocm/api/utils/mime"
)

const (
COMPONENT = "acme.org/test"
VERSION = "v1"
)

var _ = Describe("add resources", func() {
var ctx ocm.Context
var cv ocm.ComponentVersionAccess
Expand Down
4 changes: 2 additions & 2 deletions api/ocm/compdesc/meta/v1/resourceref.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ type ResourceReference struct {
ReferencePath []Identity `json:"referencePath,omitempty"`
}

func NewResourceRef(id Identity) ResourceReference {
return ResourceReference{Resource: id}
func NewResourceRef(id Identity, path ...Identity) ResourceReference {
return ResourceReference{Resource: id, ReferencePath: path}
}

func NewNestedResourceRef(id Identity, path []Identity) ResourceReference {
Expand Down
1 change: 1 addition & 0 deletions api/ocm/cpi/accspeccpi/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type (
CosumerIdentityProvider = credentials.ConsumerIdentityProvider

ComponentVersionAccess = internal.ComponentVersionAccess
DigestSpecProvider = internal.DigestSpecProvider
)

var (
Expand Down
13 changes: 13 additions & 0 deletions api/ocm/cpi/accspeccpi/methodview.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/opencontainers/go-digest"

"ocm.software/ocm/api/credentials"
metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
"ocm.software/ocm/api/utils"
"ocm.software/ocm/api/utils/blobaccess/blobaccess"
"ocm.software/ocm/api/utils/refmgmt"
Expand Down Expand Up @@ -47,6 +48,9 @@ func BlobAccessForAccessSpec(spec AccessSpec, cv ComponentVersionAccess) (blobac
}

func accessMethodViewCreator(impl AccessMethodImpl, view *refmgmt.View[AccessMethod]) AccessMethod {
if _, ok := impl.(DigestSpecProvider); ok {
return &accessMethodViewWithDigest{accessMethodView{view, impl}}
}
return &accessMethodView{view, impl}
}

Expand All @@ -55,11 +59,20 @@ type accessMethodView struct {
methodimpl AccessMethodImpl
}

type accessMethodViewWithDigest struct {
accessMethodView
}

var (
_ AccessMethodView = (*accessMethodView)(nil)
_ credentials.ConsumerIdentityProvider = (*accessMethodView)(nil)
_ DigestSpecProvider = (*accessMethodViewWithDigest)(nil)
)

func (a *accessMethodViewWithDigest) GetDigestSpec() (*metav1.DigestSpec, error) {
return a.methodimpl.(DigestSpecProvider).GetDigestSpec()
}

func (a *accessMethodView) Unwrap() interface{} {
return a.methodimpl
}
Expand Down
7 changes: 6 additions & 1 deletion api/ocm/cpi/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ type (
GenericRepositorySpec = internal.GenericRepositorySpec
RepositoryType = internal.RepositoryType
ComponentReference = internal.ComponentReference
DigestSpecProvider = internal.DigestSpecProvider
)

type ArtifactAccess[M any] internal.ArtifactAccess[M]
type ArtifactAccess[M any] interface {
internal.ArtifactAccess[M]
}

type (
BlobHandler = internal.BlobHandler
Expand Down Expand Up @@ -194,6 +197,8 @@ const (
KIND_RESOURCE = internal.KIND_RESOURCE
KIND_SOURCE = internal.KIND_SOURCE
KIND_REFERENCE = internal.KIND_REFERENCE
KIND_REPOSITORYSPEC = internal.KIND_REPOSITORYSPEC
KIND_OCM_REFERENCE = internal.KIND_OCM_REFERENCE
)

func ErrComponentVersionNotFound(name, version string) error {
Expand Down
92 changes: 92 additions & 0 deletions api/ocm/cpi/ref.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package cpi

import (
"strings"
"sync"

"github.com/mandelsoft/goutils/errors"
"github.com/mandelsoft/goutils/general"

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

type ParseHandler func(u *UniformRepositorySpec) error
Expand Down Expand Up @@ -45,3 +51,89 @@ func GetRefParseHandler(ty string, h ParseHandler) {
func HandleRef(u UniformRepositorySpec) (UniformRepositorySpec, error) {
return parseregistry.Handle(u)
}

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

// ParseRepo parses a standard ocm repository reference into a internal representation.
func ParseRepo(ref string) (UniformRepositorySpec, error) {
create := false
if strings.HasPrefix(ref, "+") {
create = true
ref = ref[1:]
}
if strings.HasPrefix(ref, ".") || strings.HasPrefix(ref, "/") {
return HandleRef(UniformRepositorySpec{
Info: ref,
CreateIfMissing: create,
})
}
match := grammar.AnchoredRepositoryRegexp.FindSubmatch([]byte(ref))
if match != nil {
h := string(match[1])
t, _ := grammar.SplitTypeSpec(h)
return HandleRef(UniformRepositorySpec{
Type: t,
TypeHint: h,
Scheme: string(match[2]),
Host: string(match[3]),
SubPath: string(match[4]),
CreateIfMissing: create,
})
}

match = grammar.AnchoredSchemedHostPortRepositoryRegexp.FindSubmatch([]byte(ref))
if match != nil {
h := string(match[1])
t, _ := grammar.SplitTypeSpec(h)
return HandleRef(UniformRepositorySpec{
Type: t,
TypeHint: h,
Scheme: string(match[2]),
Host: string(match[3]),
SubPath: string(match[4]),
CreateIfMissing: create,
})
}

match = grammar.AnchoredHostWithPortRepositoryRegexp.FindSubmatch([]byte(ref))
if match != nil {
h := string(match[1])
t, _ := grammar.SplitTypeSpec(h)
return HandleRef(UniformRepositorySpec{
Type: t,
TypeHint: h,
Scheme: string(match[2]),
Host: string(match[3]),
SubPath: string(match[4]),
CreateIfMissing: create,
})
}

match = grammar.AnchoredGenericRepositoryRegexp.FindSubmatch([]byte(ref))
if match == nil {
return UniformRepositorySpec{}, errors.ErrInvalid(KIND_OCM_REFERENCE, ref)
}
h := string(match[1])
t, _ := grammar.SplitTypeSpec(h)
return HandleRef(UniformRepositorySpec{
Type: t,
TypeHint: h,
Info: string(match[2]),
CreateIfMissing: create,
})
}

func ParseRepoToSpec(ctx Context, ref string, create ...bool) (RepositorySpec, error) {
uni, err := ParseRepo(ref)
if err != nil {
return nil, errors.ErrInvalidWrap(err, KIND_REPOSITORYSPEC, ref)
}
if !uni.CreateIfMissing {
uni.CreateIfMissing = general.Optional(create...)
}
repoSpec, err := ctx.MapUniformRepositorySpec(&uni)
if err != nil {
return nil, errors.ErrInvalidWrap(err, KIND_REPOSITORYSPEC, ref)
}
return repoSpec, nil
}
5 changes: 3 additions & 2 deletions api/ocm/cpi/repocpi/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
)

type (
Context = internal.Context
Repository = internal.Repository
Context = internal.Context
Repository = internal.Repository
DigestSpecProvider = internal.DigestSpecProvider
)
28 changes: 22 additions & 6 deletions api/ocm/cpi/repocpi/view_cv.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,14 +401,30 @@ func (c *componentVersionAccessView) SetResource(meta *cpi.ResourceMeta, acc com

// evaluate given digesting constraints and settings
hashAlgo, digester, digest := c.evaluateResourceDigest(res, old, *opts)
digestForwarded := false
if digest == "" {
if p, ok := meth.(DigestSpecProvider); ok {
dig, err := p.GetDigestSpec()
if dig != nil && err == nil {
// always prefer already known digest with its method
// if no concrete digest value is given by the caller
digest = dig.Value
hashAlgo = dig.HashAlgorithm
digester.HashAlgorithm = hashAlgo
digester.NormalizationAlgorithm = dig.NormalisationAlgorithm
digestForwarded = true
}
}
}

hasher := opts.GetHasher(hashAlgo)
if digester.HashAlgorithm == "" && hasher == nil {
if hasher == nil {
return errors.ErrUnknown(compdesc.KIND_HASH_ALGORITHM, hashAlgo)
}

if !compdesc.IsNoneAccessKind(res.Access.GetKind()) {
var calculatedDigest *cpi.DigestDescriptor
if (!opts.IsSkipVerify() && digest != "") || (!opts.IsSkipDigest() && digest == "") {
if (!opts.IsSkipVerify() && !digestForwarded && digest != "") || (!opts.IsSkipDigest() && digest == "") {
dig, err := ctx.BlobDigesters().DetermineDigests(res.Type, hasher, opts.HasherProvider, meth, digester)
if err != nil {
return err
Expand All @@ -417,11 +433,11 @@ func (c *componentVersionAccessView) SetResource(meta *cpi.ResourceMeta, acc com
return fmt.Errorf("%s: no digester accepts resource", res.Name)
}
calculatedDigest = &dig[0]
}

if digest != "" && !opts.IsSkipVerify() {
if digest != calculatedDigest.Value {
return fmt.Errorf("digest mismatch: %s != %s", calculatedDigest.Value, digest)
if digest != "" && !opts.IsSkipVerify() {
if digest != calculatedDigest.Value {
return fmt.Errorf("digest mismatch: %s != %s", calculatedDigest.Value, digest)
}
}
}

Expand Down
38 changes: 38 additions & 0 deletions api/ocm/elements/artifactaccess/ocmaccess/forward.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ocmaccess

import (
metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
"ocm.software/ocm/api/ocm/cpi"
"ocm.software/ocm/api/ocm/selectors/rscsel"
"ocm.software/ocm/api/utils/blobaccess/ocm"
)

////////////////////////////////////////////////////////////////////////////////
// Component Version

func ByComponentVersion(cv cpi.ComponentVersionAccess) ocm.ComponentVersionProvider {
return ocm.ByComponentVersion(cv)
}

func ByResolverAndName(resolver cpi.ComponentVersionResolver, comp, vers string) ocm.ComponentVersionProvider {
return ocm.ByResolverAndName(resolver, comp, vers)
}

func ByRepositorySpecAndName(ctx cpi.ContextProvider, spec cpi.RepositorySpec, comp, vers string) ocm.ComponentVersionProvider {
return ocm.ByRepositorySpecAndName(ctx, spec, comp, vers)
}

////////////////////////////////////////////////////////////////////////////////
// Resource

func ByResourceId(id metav1.Identity) ocm.ResourceProvider {
return ocm.ByResourceId(id)
}

func ByResourcePath(id metav1.Identity, path ...metav1.Identity) ocm.ResourceProvider {
return ocm.ByResourcePath(id, path...)
}

func ByResourceSelector(sel ...rscsel.Selector) ocm.ResourceProvider {
return ocm.ByResourceSelector(sel...)
}
Loading
Loading