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

fix: context base resolvers used to resolve components #1205

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
15 changes: 12 additions & 3 deletions api/ocm/internal/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,22 @@ type (
MimeType = blobaccess.MimeType
)

// VersionLookup is the interface used to resolve component versions
// in any context (especially for a ComponentAccess).
type VersionLookup interface {
ListVersions() ([]string, error)
HasVersion(vers string) (bool, error)
LookupVersion(version string) (ComponentVersionAccess, error)
}

type ComponentAccess interface {
resource.ResourceView[ComponentAccess]

GetContext() Context
GetName() string

ListVersions() ([]string, error)
LookupVersion(version string) (ComponentVersionAccess, error)
HasVersion(vers string) (bool, error)
VersionLookup

NewVersion(version string, overrides ...bool) (ComponentVersionAccess, error)
AddVersion(cv ComponentVersionAccess, overrides ...bool) error
AddVersionOpt(cv ComponentVersionAccess, opts ...AddVersionOption) error
Expand Down Expand Up @@ -118,6 +125,8 @@ type ComponentVersionAccess interface {
ReadOnlyFeature

GetContext() Context
// Repository returns the backing repository object without an additional
// ref. It should not be closed.
Repository() Repository
GetDescriptor() *compdesc.ComponentDescriptor

Expand Down
64 changes: 64 additions & 0 deletions api/ocm/resolvers/forward.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package resolvers

import (
"github.com/mandelsoft/goutils/errors"
"golang.org/x/exp/maps"

"ocm.software/ocm/api/ocm/internal"
common "ocm.software/ocm/api/utils/misc"
)

type (
ContextProvider = internal.ContextProvider
RepositorySpec = internal.RepositorySpec
VersionLookup = internal.VersionLookup
ComponentVersionAccess = internal.ComponentVersionAccess
ComponentVersionResolver = internal.ComponentVersionResolver
ComponentResolver = internal.ComponentResolver
Expand All @@ -25,3 +30,62 @@ const (
func NewResolverRule(prefix string, spec RepositorySpec, prio ...int) ResolverRule {
return internal.NewResolverRule(prefix, spec, prio...)
}

// VersionResolverForComponent provides a VersionLookup for a component resolver.
// It resolves all versions provided by a component known to a ComponentResolver.
// The version set may be composed by versions of the component found in
// multiple repositories according to the result of the ComponentResolver.
func VersionResolverForComponent(name string, resolver ComponentResolver) (VersionLookup, error) {
crs := resolver.LookupComponentProviders(name)
if len(crs) == 0 {
return nil, errors.ErrNotFound(KIND_COMPONENT, name)
}

versions := map[string]ResolvedComponentProvider{}
for _, cr := range crs {
c, err := cr.LookupComponent(name)
if err != nil {
return nil, err
}
vers, err := c.ListVersions()
if err != nil {
return nil, err
}
for _, v := range vers {
if _, ok := versions[v]; !ok {
versions[v] = cr
}
}
}
return &versionResolver{name, versions}, nil
}

type versionResolver struct {
comp string
versions map[string]ResolvedComponentProvider
}

func (v *versionResolver) ListVersions() ([]string, error) {
return maps.Keys(v.versions), nil
}

func (v *versionResolver) LookupVersion(version string) (ComponentVersionAccess, error) {
p := v.versions[version]
if p == nil {
return nil, errors.ErrNotFound(KIND_COMPONENTVERSION, common.NewNameVersion(v.comp, version).String())
}
vp, err := p.LookupComponent(v.comp)
if err != nil {
return nil, err
}
return vp.LookupVersion(version)
}

func (v *versionResolver) HasVersion(vers string) (bool, error) {
cv, err := v.LookupVersion(vers)
if err != nil {
return false, err
}
defer cv.Close()
return cv != nil, nil
}
34 changes: 19 additions & 15 deletions api/ocm/resolvers/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,29 @@ var _ = Describe("resolver", func() {
env.Cleanup()
})

It("lookup cv per standard resolver", func() {
// ocmlog.Context().AddRule(logging.NewConditionRule(logging.TraceLevel, accessio.ALLOC_REALM))
Context("resolver", func() {
var ctx ocm.Context

ctx := ocm.New()
BeforeEach(func() {
ctx = ocm.New()
spec := Must(ctf.NewRepositorySpec(accessobj.ACC_READONLY, ARCH, env))
ctx.AddResolverRule("ocm.software", spec, 10)
})

spec := Must(ctf.NewRepositorySpec(accessobj.ACC_READONLY, ARCH, env))
ctx.AddResolverRule("ocm.software", spec, 10)
It("lookup cv per standard resolver", func() {
cv := Must(ctx.GetResolver().LookupComponentVersion(COMPONENT, VERSION))
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
})

cv := Must(ctx.GetResolver().LookupComponentVersion(COMPONENT, VERSION))
It("lookup cv per version resolver", func() {
vr := Must(resolvers.VersionResolverForComponent(COMPONENT, ctx.GetResolver().(resolvers.ComponentResolver)))
Expect(vr.ListVersions()).To(ContainElements(VERSION))

/*
err := cv.Repository().Close()
if err != nil {
defer cv.Close()
Expect(err).To(Succeed())
}
*/
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
cv := Must(vr.LookupVersion(VERSION))
Close(cv)
Expect(ctx.Finalize()).To(Succeed())
})
})

It("orders resolver rules", func() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"ocm.software/ocm/api/ocm"
"ocm.software/ocm/api/ocm/compdesc"
metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1"
"ocm.software/ocm/api/ocm/resolvers"
common "ocm.software/ocm/api/utils/misc"
"ocm.software/ocm/api/utils/semverutils"
"ocm.software/ocm/cmds/ocm/common/output"
Expand Down Expand Up @@ -148,7 +149,7 @@ func (h *TypeHandler) filterVersions(vers []string) ([]string, error) {
}

func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]output.Object, error) {
var component ocm.ComponentAccess
var component resolvers.VersionLookup
var result []output.Object
var err error

Expand Down Expand Up @@ -176,11 +177,25 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
evaluated.Repository = cv.Repository()
h.session.Closer(cv)
}
} else {
// if the resolver is a component resolver, we can use it to list all available version
// cross all repositories found for the given component.
if cr, ok := h.resolver.(resolvers.ComponentResolver); ok {
cvr, err := resolvers.VersionResolverForComponent(comp.Component, cr)
if err != nil {
return nil, err
}
component = cvr
evaluated = &ocm.EvaluationResult{}
evaluated.Ref.CompSpec = comp
}
}
}
if evaluated == nil {
return nil, errors.Wrapf(err, "%s: invalid component version reference", name)
}
} else {
component = evaluated.Component
}
if evaluated.Version != nil {
result = append(result, &Object{
Expand All @@ -192,7 +207,6 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
return result, nil
}
spec = evaluated.Ref
component = evaluated.Component
repo = evaluated.Repository
} else {
comp := ocm.CompSpec{Component: ""}
Expand Down Expand Up @@ -247,7 +261,7 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
s := spec
s.Version = &t
result = append(result, &Object{
Repository: repo,
Repository: v.Repository(),
Spec: s,
// Component: component,
ComponentVersion: v,
Expand Down
Loading