diff --git a/cmds/ocm/app/app.go b/cmds/ocm/app/app.go index 7d30fe595..b735d0666 100644 --- a/cmds/ocm/app/app.go +++ b/cmds/ocm/app/app.go @@ -76,6 +76,7 @@ type CLIOptions struct { LogLevel string LogFile string LogConfig string + Version bool logFile vfs.File } @@ -249,6 +250,7 @@ func (o *CLIOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVarP(&o.LogLevel, "loglevel", "l", "", "set log level") fs.StringVarP(&o.LogFile, "logfile", "L", "", "set log file") fs.StringVarP(&o.LogConfig, "logconfig", "", "", "log config") + fs.BoolVarP(&o.Version, "version", "", false, "show version") // otherwise it is implicitly added by cobra } func (o *CLIOptions) Close() error { diff --git a/docs/reference/ocm.md b/docs/reference/ocm.md index 091e32008..5a627b665 100644 --- a/docs/reference/ocm.md +++ b/docs/reference/ocm.md @@ -17,6 +17,7 @@ ocm [] ... -L, --logfile string set log file -l, --loglevel string set log level -v, --verbose enable verbose logging + --version show version ``` ### Description diff --git a/pkg/contexts/ocm/compdesc/componentdescriptor.go b/pkg/contexts/ocm/compdesc/componentdescriptor.go index d5e4deb2e..3ce00df8e 100644 --- a/pkg/contexts/ocm/compdesc/componentdescriptor.go +++ b/pkg/contexts/ocm/compdesc/componentdescriptor.go @@ -16,6 +16,8 @@ import ( var NotFound = errors.ErrNotFound() +const KIND_REFERENCE = "component reference" + type ( ObjectMeta = metav1.ObjectMeta Provider = metav1.Provider diff --git a/pkg/contexts/ocm/compdesc/helper.go b/pkg/contexts/ocm/compdesc/helper.go index eccbc4deb..69272b525 100644 --- a/pkg/contexts/ocm/compdesc/helper.go +++ b/pkg/contexts/ocm/compdesc/helper.go @@ -9,6 +9,7 @@ import ( "fmt" v1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1" + "github.com/open-component-model/ocm/pkg/errors" "github.com/open-component-model/ocm/pkg/runtime" "github.com/open-component-model/ocm/pkg/utils/selector" ) @@ -325,7 +326,7 @@ func (cd *ComponentDescriptor) GetReferenceByIdentity(id v1.Identity) (Component return ref, nil } } - return ComponentReference{}, NotFound + return ComponentReference{}, errors.ErrNotFound(KIND_REFERENCE, id.String()) } // GetReferenceIndex returns the index of a given source. diff --git a/pkg/contexts/ocm/cpi/support/compversaccess.go b/pkg/contexts/ocm/cpi/support/compversaccess.go index c239ead0f..9329d5f19 100644 --- a/pkg/contexts/ocm/cpi/support/compversaccess.go +++ b/pkg/contexts/ocm/cpi/support/compversaccess.go @@ -23,6 +23,13 @@ type ComponentVersionAccess struct { // implemented by view // the rest is directly taken from the artifact set implementation +func (s *ComponentVersionAccess) Dup() (cpi.ComponentVersionAccess, error) { + if s.view.IsClosed() { + return nil, accessio.ErrClosed + } + return s.componentVersionAccessImpl.Dup() +} + func (s *ComponentVersionAccess) Close() error { err := s.Update(true) if err != nil { diff --git a/pkg/contexts/ocm/internal/errors.go b/pkg/contexts/ocm/internal/errors.go index fb3d143ac..90c1e896e 100644 --- a/pkg/contexts/ocm/internal/errors.go +++ b/pkg/contexts/ocm/internal/errors.go @@ -7,6 +7,7 @@ package internal import ( "fmt" + "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc" "github.com/open-component-model/ocm/pkg/errors" ) @@ -14,7 +15,7 @@ const ( KIND_COMPONENTVERSION = "component version" KIND_RESOURCE = "component resource" KIND_SOURCE = "component source" - KIND_REFERENCE = "component reference" + KIND_REFERENCE = compdesc.KIND_REFERENCE ) func ErrComponentVersionNotFound(name, version string) error { diff --git a/pkg/contexts/ocm/repositories/genericocireg/component.go b/pkg/contexts/ocm/repositories/genericocireg/component.go index d7d578bbe..b49503fb8 100644 --- a/pkg/contexts/ocm/repositories/genericocireg/component.go +++ b/pkg/contexts/ocm/repositories/genericocireg/component.go @@ -23,6 +23,13 @@ type ComponentAccess struct { // implemented by view // the rest is directly taken from the artifact set implementation +func (s *ComponentAccess) Dup() (cpi.ComponentAccess, error) { + if s.view.IsClosed() { + return nil, accessio.ErrClosed + } + return s.componentAccessImpl.Dup() +} + func (s *ComponentAccess) Close() error { return s.view.Close() } diff --git a/pkg/contexts/ocm/utils/resourceref.go b/pkg/contexts/ocm/utils/resourceref.go index 2f8fab219..0ef70cc92 100644 --- a/pkg/contexts/ocm/utils/resourceref.go +++ b/pkg/contexts/ocm/utils/resourceref.go @@ -7,6 +7,7 @@ package utils import ( "fmt" + "github.com/open-component-model/ocm/pkg/common" "github.com/open-component-model/ocm/pkg/contexts/ocm" metav1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1" "github.com/open-component-model/ocm/pkg/errors" @@ -19,7 +20,7 @@ func ResolveReferencePath(cv ocm.ComponentVersionAccess, path []metav1.Identity, } eff, err := cv.Dup() if err != nil { - return nil, err + return nil, errors.Wrapf(err, "component version already closed") } var final utils.Finalizer @@ -27,18 +28,18 @@ func ResolveReferencePath(cv ocm.ComponentVersionAccess, path []metav1.Identity, for _, cr := range path { final.Close(eff) - compoundResolver := ocm.NewCompoundResolver(eff.Repository(), resolver) cref, err := eff.GetReference(cr) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "%s", common.VersionedElementKey(cv)) } + compoundResolver := ocm.NewCompoundResolver(eff.Repository(), resolver) eff, err = compoundResolver.LookupComponentVersion(cref.GetComponentName(), cref.GetVersion()) if err != nil { - return nil, errors.Wrapf(err, "cannot resolve component reference") + return nil, errors.Wrapf(err, "cannot resolve component version for reference %s", cr.String()) } if eff == nil { - return nil, errors.ErrNotFound(ocm.KIND_COMPONENTREFERENCE, cref.String()) + return nil, errors.ErrNotFound(ocm.KIND_COMPONENTVERSION, cref.String()) } final.Finalize() } diff --git a/pkg/contexts/ocm/utils/resourceref_test.go b/pkg/contexts/ocm/utils/resourceref_test.go index f1fc5d141..608286364 100644 --- a/pkg/contexts/ocm/utils/resourceref_test.go +++ b/pkg/contexts/ocm/utils/resourceref_test.go @@ -13,6 +13,7 @@ import ( "github.com/open-component-model/ocm/pkg/common/accessio" "github.com/open-component-model/ocm/pkg/common/accessobj" + "github.com/open-component-model/ocm/pkg/contexts/ocm" metav1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1" "github.com/open-component-model/ocm/pkg/contexts/ocm/repositories/ctf" "github.com/open-component-model/ocm/pkg/contexts/ocm/utils" @@ -32,6 +33,16 @@ const OCIHOST = "alias" const SIGNATURE = "test" const SIGN_ALGO = rsa.Algorithm +func Check(cv ocm.ComponentVersionAccess, name string, path ...metav1.Identity) { + ref := metav1.NewNestedResourceRef(metav1.NewIdentity(name), path) + res, eff, err := utils.ResolveResourceReference(cv, ref, nil) + ExpectWithOffset(1, err).To(Succeed()) + defer Close(eff) + m := Must(res.AccessMethod()) + data := Must(m.Get()) + ExpectWithOffset(1, string(data)).To(Equal(name)) +} + var _ = Describe("resolving local resource references", func() { var env *Builder @@ -79,14 +90,7 @@ var _ = Describe("resolving local resource references", func() { cv := Must(src.LookupComponentVersion(COMPONENT3, VERSION)) defer Close(cv) - ref := metav1.NewResourceRef(metav1.NewIdentity("topdata")) - - res, eff, err := utils.ResolveResourceReference(cv, ref, nil) - Expect(err).To(Succeed()) - m := Must(res.AccessMethod()) - data := Must(m.Get()) - Expect(string(data)).To(Equal("topdata")) - MustBeSuccessful(eff.Close()) + Check(cv, "topdata") }) It("resolves an indirect resource", func() { @@ -95,14 +99,7 @@ var _ = Describe("resolving local resource references", func() { cv := Must(src.LookupComponentVersion(COMPONENT3, VERSION)) defer Close(cv) - ref := metav1.NewNestedResourceRef(metav1.NewIdentity("otherdata"), []metav1.Identity{metav1.NewIdentity("nested")}) - - res, eff, err := utils.ResolveResourceReference(cv, ref, nil) - Expect(err).To(Succeed()) - m := Must(res.AccessMethod()) - data := Must(m.Get()) - Expect(string(data)).To(Equal("otherdata")) - MustBeSuccessful(eff.Close()) + Check(cv, "otherdata", metav1.NewIdentity("nested")) }) It("skips an intermediate component version", func() { @@ -111,14 +108,31 @@ var _ = Describe("resolving local resource references", func() { cv := Must(src.LookupComponentVersion(COMPONENT3, VERSION)) defer Close(cv) - ref := metav1.NewNestedResourceRef(metav1.NewIdentity("testdata"), []metav1.Identity{metav1.NewIdentity("nested"), metav1.NewIdentity("ref")}) + Check(cv, "testdata", metav1.NewIdentity("nested"), metav1.NewIdentity("ref")) + }) + + It("multiple lookups", func() { + src := Must(ctf.Open(env.OCMContext(), accessobj.ACC_READONLY, ARCH, 0, env)) + defer Close(src) + cv := Must(src.LookupComponentVersion(COMPONENT3, VERSION)) + defer Close(cv) + + Check(cv, "testdata", metav1.NewIdentity("nested"), metav1.NewIdentity("ref")) + Check(cv, "otherdata", metav1.NewIdentity("nested")) + Check(cv, "topdata") + }) - res, eff, err := utils.ResolveResourceReference(cv, ref, nil) - Expect(err).To(Succeed()) - defer Close(eff) + It("access closed", func() { + src := Must(ctf.Open(env.OCMContext(), accessobj.ACC_READONLY, ARCH, 0, env)) + defer Close(src) + cv := Must(src.LookupComponentVersion(COMPONENT3, VERSION)) + defer Close(cv) - m := Must(res.AccessMethod()) - data := Must(m.Get()) - Expect(string(data)).To(Equal("testdata")) + dup := Must(cv.Dup()) + Close(dup) + + ref := metav1.NewResourceRef(metav1.NewIdentity("topdata")) + _, _, err := utils.ResolveResourceReference(dup, ref, nil) + MustFailWithMessage(err, "component version already closed: closed") }) }) diff --git a/pkg/testutils/utils.go b/pkg/testutils/utils.go index 97ac89e6d..387581e07 100644 --- a/pkg/testutils/utils.go +++ b/pkg/testutils/utils.go @@ -31,6 +31,11 @@ func Must[T any](o T, err error) T { return o } +func MustWithOffset[T any](offset int, o T, err error) T { + ExpectWithOffset(offset+1, err).To(Succeed()) + return o +} + func MustBeNonNil[T any](o T) T { ExpectWithOffset(1, o).NotTo(BeNil()) return o