diff --git a/api/ocm/compdesc/accessors.go b/api/ocm/compdesc/accessors.go index a691c79f89..56fdcb56a1 100644 --- a/api/ocm/compdesc/accessors.go +++ b/api/ocm/compdesc/accessors.go @@ -1,7 +1,6 @@ package compdesc import ( - "ocm.software/ocm/api/ocm/compdesc/equivalent" metav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" "ocm.software/ocm/api/ocm/selectors/accessors" ) @@ -38,19 +37,16 @@ type ObjectMetaAccessor interface { } // ElementMetaAccessor provides generic access an elements meta information. -type ElementMetaAccessor interface { - ElementMetaProvider - Equivalent(ElementMetaAccessor) equivalent.EqualState -} +// Deprecated: use Element. +type ElementMetaAccessor = accessors.Element -// ElementAccessor provides generic access to list of elements. -type ElementAccessor interface { - Len() int - Get(i int) ElementMetaAccessor -} +type Element = accessors.Element + +// ElementListAccessor provides generic access to list of elements. +type ElementListAccessor = accessors.ElementListAccessor type ElementMetaProvider interface { - GetMeta() *ElementMeta + GetMeta() accessors.ElementMeta } // ElementArtifactAccessor provides access to generic artifact information of an element. @@ -69,7 +65,7 @@ type ElementDigestAccessor interface { // ArtifactAccessor provides generic access to list of artifacts. // There are resources or sources. type ArtifactAccessor interface { - ElementAccessor + ElementListAccessor GetArtifact(i int) ElementArtifactAccessor } diff --git a/api/ocm/compdesc/componentdescriptor.go b/api/ocm/compdesc/componentdescriptor.go index bf111c8029..30b7d05273 100644 --- a/api/ocm/compdesc/componentdescriptor.go +++ b/api/ocm/compdesc/componentdescriptor.go @@ -17,6 +17,7 @@ import ( const InternalSchemaVersion = "internal" +// Deprecated: as result of the new select function an empty list is returned instead of an error. var NotFound = errors.ErrNotFound() const ( @@ -127,7 +128,7 @@ const ( type ElementMetaAccess interface { GetName() string GetVersion() string - GetIdentity(accessor ElementAccessor) metav1.Identity + GetIdentity(accessor ElementListAccessor) metav1.Identity GetLabels() metav1.Labels } @@ -166,7 +167,7 @@ func (o *ElementMeta) GetName() string { } // GetMeta returns the element meta. -func (r *ElementMeta) GetMeta() *ElementMeta { +func (r *ElementMeta) GetMeta() accessors.ElementMeta { return r } @@ -231,7 +232,7 @@ func (o *ElementMeta) AddExtraIdentity(identity metav1.Identity) { } // GetIdentity returns the identity of the object. -func (o *ElementMeta) GetIdentity(accessor ElementAccessor) metav1.Identity { +func (o *ElementMeta) GetIdentity(accessor ElementListAccessor) metav1.Identity { identity := o.ExtraIdentity.Copy() if identity == nil { identity = metav1.Identity{} @@ -242,7 +243,7 @@ func (o *ElementMeta) GetIdentity(accessor ElementAccessor) metav1.Identity { l := accessor.Len() for i := 0; i < l; i++ { m := accessor.Get(i).GetMeta() - if m.Name == o.Name && m.ExtraIdentity.Equals(o.ExtraIdentity) { + if m.GetName() == o.Name && m.GetExtraIdentity().Equals(o.ExtraIdentity) { if found { identity[SystemIdentityVersion] = o.Version @@ -255,32 +256,7 @@ func (o *ElementMeta) GetIdentity(accessor ElementAccessor) metav1.Identity { return identity } -// GetIdentityForContext returns the identity of the object. -func (o *ElementMeta) GetIdentityForContext(accessor accessors.ElementListAccessor) metav1.Identity { - identity := o.ExtraIdentity.Copy() - if identity == nil { - identity = metav1.Identity{} - } - identity[SystemIdentityName] = o.Name - if accessor != nil { - found := false - l := accessor.Len() - for i := 0; i < l; i++ { - m := accessor.Get(i).GetMeta() - if m.GetName() == o.GetName() && m.GetExtraIdentity().Equals(o.ExtraIdentity) { - if found { - identity[SystemIdentityVersion] = o.Version - - break - } - found = true - } - } - } - return identity -} - -// GetRawIdentity returns the identity plus version. +// GetRawIdentity returns the identity plus version, if set. func (o *ElementMeta) GetRawIdentity() metav1.Identity { identity := o.ExtraIdentity.Copy() if identity == nil { @@ -306,7 +282,7 @@ func (o *ElementMeta) GetMatchBaseIdentity() metav1.Identity { } // GetIdentityDigest returns the digest of the object's identity. -func (o *ElementMeta) GetIdentityDigest(accessor ElementAccessor) []byte { +func (o *ElementMeta) GetIdentityDigest(accessor ElementListAccessor) []byte { return o.GetIdentity(accessor).Digest() } @@ -337,7 +313,7 @@ func (o *ElementMeta) Equivalent(a *ElementMeta) equivalent.EqualState { return state.Apply(o.Labels.Equivalent(a.Labels)) } -func GetByIdentity(a ElementAccessor, id metav1.Identity) ElementMetaAccessor { +func GetByIdentity(a ElementListAccessor, id metav1.Identity) ElementMetaAccessor { l := a.Len() for i := 0; i < l; i++ { e := a.Get(i) @@ -348,7 +324,7 @@ func GetByIdentity(a ElementAccessor, id metav1.Identity) ElementMetaAccessor { return nil } -func GetIndexByIdentity(a ElementAccessor, id metav1.Identity) int { +func GetIndexByIdentity(a ElementListAccessor, id metav1.Identity) int { l := a.Len() for i := 0; i < l; i++ { e := a.Get(i) @@ -375,7 +351,7 @@ func GenericAccessSpec(un *runtime.UnstructuredTypedObject) AccessSpec { // Sources describes a set of source specifications. type Sources []Source -var _ ElementAccessor = Sources{} +var _ ElementListAccessor = Sources{} func SourceArtifacts(cd *ComponentDescriptor) ArtifactAccessor { return cd.Sources @@ -538,7 +514,7 @@ func (r SourceRefs) Copy() SourceRefs { // Resources describes a set of resource specifications. type Resources []Resource -var _ ElementAccessor = Resources{} +var _ ElementListAccessor = Resources{} func ResourceArtifacts(cd *ComponentDescriptor) ArtifactAccessor { return cd.Resources diff --git a/api/ocm/compdesc/deprecated.go b/api/ocm/compdesc/deprecated.go index cea854ea08..d33058d04c 100644 --- a/api/ocm/compdesc/deprecated.go +++ b/api/ocm/compdesc/deprecated.go @@ -221,7 +221,7 @@ func (cd *ComponentDescriptor) GetComponentReferences(selectors ...IdentitySelec // If the index is not found -1 is returned. // Deprecated: use GetReferenceIndex. func (cd *ComponentDescriptor) GetComponentReferenceIndex(ref Reference) int { - return cd.GetReferenceIndex(ref.GetMeta()) + return cd.GetReferenceIndex(&ref) } // GetReferenceAccessByIdentity returns a pointer to the reference that matches the given identity. diff --git a/api/ocm/compdesc/equal.go b/api/ocm/compdesc/equal.go index 9d6fb8f25d..fd81d0c7da 100644 --- a/api/ocm/compdesc/equal.go +++ b/api/ocm/compdesc/equal.go @@ -41,7 +41,7 @@ func (cd *ComponentDescriptor) Equivalent(o *ComponentDescriptor) equivalent.Equ ) } -func EquivalentElems(a ElementAccessor, b ElementAccessor) equivalent.EqualState { +func EquivalentElems(a ElementListAccessor, b ElementListAccessor) equivalent.EqualState { state := equivalent.StateEquivalent() // Equivaluent of elements handles nil to provide state accoding to it diff --git a/api/ocm/compdesc/helper.go b/api/ocm/compdesc/helper.go index fa48889fe5..6e7975e4e9 100644 --- a/api/ocm/compdesc/helper.go +++ b/api/ocm/compdesc/helper.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/mandelsoft/goutils/errors" + "golang.org/x/exp/slices" v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" "ocm.software/ocm/api/ocm/selectors" @@ -40,20 +41,21 @@ func (cd *ComponentDescriptor) AddRepositoryContext(repoCtx runtime.TypedObject) return nil } -func (cd *ComponentDescriptor) SelectResources(sel ...rscsel.Selector) ([]Resource, error) { +func (cd *ComponentDescriptor) SelectResources(sel ...rscsel.Selector) (Resources, error) { err := selectors.ValidateSelectors(sel...) if err != nil { return nil, err } list := MapToSelectorElementList(cd.Resources) - result := []Resource{} + result := Resources{} +outer: for _, r := range cd.Resources { if len(sel) > 0 { mr := MapToSelectorResource(&r) for _, s := range sel { if !s.MatchResource(list, mr) { - continue + continue outer } } } @@ -62,12 +64,8 @@ func (cd *ComponentDescriptor) SelectResources(sel ...rscsel.Selector) ([]Resour return result, nil } -func (cd *ComponentDescriptor) GetResources() []Resource { - result := []Resource{} - for _, r := range cd.Resources { - result = append(result, r) - } - return result +func (cd *ComponentDescriptor) GetResources() Resources { + return slices.Clone(cd.Resources) } // GetResourceByIdentity returns resource that matches the given identity. @@ -116,20 +114,21 @@ func (cd *ComponentDescriptor) GetResourceIndex(res *ResourceMeta) int { return ElementIndex(cd.Resources, res) } -func (cd *ComponentDescriptor) SelectSources(sel ...srcsel.Selector) ([]Source, error) { +func (cd *ComponentDescriptor) SelectSources(sel ...srcsel.Selector) (Sources, error) { err := selectors.ValidateSelectors(sel...) if err != nil { return nil, err } list := MapToSelectorElementList(cd.Sources) - result := []Source{} + result := Sources{} +outer: for _, r := range cd.Sources { if len(sel) > 0 { mr := MapToSelectorSource(&r) for _, s := range sel { if !s.MatchSource(list, mr) { - continue + continue outer } } } @@ -138,12 +137,8 @@ func (cd *ComponentDescriptor) SelectSources(sel ...srcsel.Selector) ([]Source, return result, nil } -func (cd *ComponentDescriptor) GetSources() []Source { - result := []Source{} - for _, r := range cd.Sources { - result = append(result, r) - } - return result +func (cd *ComponentDescriptor) GetSources() Sources { + return slices.Clone(cd.Sources) } // GetSourceByIdentity returns source that match the given identity. @@ -185,20 +180,21 @@ func (cd *ComponentDescriptor) GetReferenceByIdentity(id v1.Identity) (Reference return Reference{}, errors.ErrNotFound(KIND_REFERENCE, id.String()) } -func (cd *ComponentDescriptor) SelectReferences(sel ...refsel.Selector) ([]Reference, error) { +func (cd *ComponentDescriptor) SelectReferences(sel ...refsel.Selector) (References, error) { err := selectors.ValidateSelectors(sel...) if err != nil { return nil, err } list := MapToSelectorElementList(cd.References) - result := []Reference{} + result := References{} +outer: for _, r := range cd.References { if len(sel) > 0 { mr := MapToSelectorReference(&r) for _, s := range sel { if !s.MatchReference(list, mr) { - continue + continue outer } } } @@ -207,12 +203,8 @@ func (cd *ComponentDescriptor) SelectReferences(sel ...refsel.Selector) ([]Refer return result, nil } -func (cd *ComponentDescriptor) GetReferences() []Reference { - result := []Reference{} - for _, r := range cd.References { - result = append(result, r) - } - return result +func (cd *ComponentDescriptor) GetReferences() References { + return slices.Clone(cd.References) } // GetReferenceIndexByIdentity returns the index of the reference that matches the given identity. diff --git a/api/ocm/compdesc/selector.go b/api/ocm/compdesc/selector.go index ef70176b2c..0434bb357c 100644 --- a/api/ocm/compdesc/selector.go +++ b/api/ocm/compdesc/selector.go @@ -7,14 +7,15 @@ import ( ) type elemList struct { - ElementAccessor + ElementListAccessor } -func (e *elemList) Get(i int) accessors.ElementMetaAccessor { - return generics.Cast[accessors.ElementMetaAccessor](e.ElementAccessor.Get(i)) +func (e *elemList) Get(i int) accessors.Element { + elem := e.ElementListAccessor.Get(i) + return generics.Cast[accessors.Element](elem) } -func MapToSelectorElementList(accessor ElementAccessor) accessors.ElementListAccessor { +func MapToSelectorElementList(accessor ElementListAccessor) accessors.ElementListAccessor { return &elemList{accessor} } diff --git a/api/ocm/compdesc/selector_test.go b/api/ocm/compdesc/selector_test.go new file mode 100644 index 0000000000..2ac85dcee3 --- /dev/null +++ b/api/ocm/compdesc/selector_test.go @@ -0,0 +1,474 @@ +package compdesc_test + +import ( + . "github.com/mandelsoft/goutils/testutils" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "ocm.software/ocm/api/ocm/selectors/labelsel" + "ocm.software/ocm/api/ocm/selectors/refsel" + "ocm.software/ocm/api/ocm/selectors/rscsel" + + "ocm.software/ocm/api/ocm/compdesc" + v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" + "ocm.software/ocm/api/ocm/extensions/repositories/ocireg" +) + +var _ = Describe("helper", func() { + It("should inject a new repository context if none is defined", func() { + cd := &compdesc.ComponentDescriptor{} + compdesc.DefaultComponent(cd) + + repoCtx := ocireg.NewRepositorySpec("example.com", nil) + Expect(cd.AddRepositoryContext(repoCtx)).To(Succeed()) + Expect(cd.RepositoryContexts).To(HaveLen(1)) + + Expect(cd.AddRepositoryContext(repoCtx)).To(Succeed()) + Expect(cd.RepositoryContexts).To(HaveLen(1)) + + repoCtx2 := ocireg.NewRepositorySpec("example.com/dev", nil) + Expect(cd.AddRepositoryContext(repoCtx2)).To(Succeed()) + Expect(cd.RepositoryContexts).To(HaveLen(2)) + }) + + Context("resource selection", func() { + cd := &compdesc.ComponentDescriptor{} + + r1v1 := compdesc.Resource{ + ResourceMeta: compdesc.ResourceMeta{ + ElementMeta: compdesc.ElementMeta{ + Name: "r1", + Version: "v1", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"labelvalue\""), + Version: "v1", + Signing: false, + }, + }, + }, + Type: "t1", + Relation: v1.LocalRelation, + }, + } + r1v2 := compdesc.Resource{ + ResourceMeta: compdesc.ResourceMeta{ + ElementMeta: compdesc.ElementMeta{ + Name: "r1", + Version: "v2", + }, + Type: "t1", + Relation: v1.LocalRelation, + }, + } + r2v1 := compdesc.Resource{ + ResourceMeta: compdesc.ResourceMeta{ + ElementMeta: compdesc.ElementMeta{ + Name: "r2", + Version: "v1", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"othervalue\""), + Version: "v1", + Signing: false, + }, + }, + }, + Type: "t2", + Relation: v1.LocalRelation, + }, + } + r3v2 := compdesc.Resource{ + ResourceMeta: compdesc.ResourceMeta{ + ElementMeta: compdesc.ElementMeta{ + Name: "r3", + Version: "v2", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"dummy\""), + Version: "v2", + Signing: false, + }, + v1.Label{ + Name: "l2", + Value: []byte("\"labelvalue\""), + Version: "v2", + Signing: true, + }, + v1.Label{ + Name: "l3", + Value: []byte("\"labelvalue\""), + Version: "v3", + }, + }, + }, + Type: "t2", + Relation: v1.LocalRelation, + }, + } + + r4v3 := compdesc.Resource{ + ResourceMeta: compdesc.ResourceMeta{ + ElementMeta: compdesc.ElementMeta{ + Name: "r4", + Version: "v3", + ExtraIdentity: v1.Identity{ + "extra": "value", + "other": "othervalue", + }, + }, + Type: "t3", + Relation: v1.LocalRelation, + }, + } + + cd.Resources = compdesc.Resources{ + r1v1, + r1v2, + r2v1, + r3v2, + r4v3, + } + + Context("id selection", func() { + It("selects by name", func() { + res := Must(cd.SelectResources(rscsel.Name("r1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r1v2})) + }) + It("selects by version", func() { + res := Must(cd.SelectResources(rscsel.Version("v1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r2v1})) + }) + It("selects by version", func() { + res := Must(cd.SelectResources(rscsel.PartialIdentityByKeyPairs("version", "v1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1})) // no r2v1: version not part of identity + }) + }) + + Context("attr selection", func() { + It("selects by name", func() { + res := Must(cd.SelectResources(rscsel.Name("r1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r1v2})) + }) + It("selects by version", func() { + res := Must(cd.SelectResources(rscsel.Version("v1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r2v1})) + }) + It("selects by type", func() { + res := Must(cd.SelectResources(rscsel.ResourceType("t2"))) + Expect(res).To(Equal(compdesc.Resources{r2v1, r3v2})) + }) + + It("selects by label name", func() { + res := Must(cd.SelectResources(rscsel.LabelName("l1"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r2v1, r3v2})) + }) + It("selects by label version", func() { + res := Must(cd.SelectResources(rscsel.LabelVersion("v2"))) + Expect(res).To(Equal(compdesc.Resources{r3v2})) + }) + It("selects by label value", func() { + res := Must(cd.SelectResources(rscsel.LabelValue("labelvalue"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r3v2})) + }) + It("selects unrelated by label name and value", func() { + res := Must(cd.SelectResources(rscsel.LabelName("l1"), rscsel.LabelValue("labelvalue"))) + Expect(res).To(Equal(compdesc.Resources{r1v1, r3v2})) // unrelated checks at resource level + }) + It("selects related by label name and value", func() { + res := Must(cd.SelectResources(rscsel.Label(labelsel.Name("l1"), labelsel.Value("labelvalue")))) + Expect(res).To(Equal(compdesc.Resources{r1v1})) // related checks at label level + }) + It("selects by signed label", func() { + res := Must(cd.SelectResources(labelsel.Signed())) + Expect(res).To(Equal(compdesc.Resources{r3v2})) + }) + + It("selects with extra identity", func() { + res := Must(cd.SelectResources(rscsel.ExtraIdentityByKeyPairs("extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.Resources{r4v3})) + }) + + It("selects none with wrong extra identity value", func() { + res := Must(cd.SelectResources(rscsel.ExtraIdentityByKeyPairs("extra", "other"))) + Expect(res).To(BeEmpty()) + }) + + It("selects none with wrong extra identity key", func() { + res := Must(cd.SelectResources(rscsel.ExtraIdentityByKeyPairs("extra2", "value"))) + Expect(res).To(BeEmpty()) + }) + + It("selects by or", func() { + res := Must(cd.SelectResources(rscsel.Or(rscsel.Name("r3"), rscsel.Version("v2")))) + Expect(res).To(Equal(compdesc.Resources{r1v2, r3v2})) + }) + + It("selects by and", func() { + res := Must(cd.SelectResources(rscsel.And(rscsel.Name("r1"), rscsel.Version("v1")))) + Expect(res).To(Equal(compdesc.Resources{r1v1})) + }) + + It("selects by negated selector", func() { + res := Must(cd.SelectResources(rscsel.Not(rscsel.Name("r1")))) + Expect(res).To(Equal(compdesc.Resources{r2v1, r3v2, r4v3})) + }) + + It("selects by identity selector", func() { + res := Must(cd.SelectResources(rscsel.IdentityByKeyPairs("r4", "extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.Resources{r4v3})) + }) + + It("selects none by identity selector with missing attribute", func() { + res := Must(cd.SelectResources(rscsel.IdentityByKeyPairs("r4", "extra", "value"))) + Expect(res).To(BeEmpty()) + }) + + It("selects by partial identity selector", func() { + res := Must(cd.SelectResources(rscsel.PartialIdentityByKeyPairs("name", "r4", "extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.Resources{r4v3})) + }) + + It("selects by partial identity selector with partial attributes", func() { + res := Must(cd.SelectResources(rscsel.PartialIdentityByKeyPairs("extra", "value"))) + Expect(res).To(Equal(compdesc.Resources{r4v3})) + }) + + It("selects none by partial identity selector with missing attribute", func() { + res := Must(cd.SelectResources(rscsel.IdentityByKeyPairs("r4", "extra", "value", "dummy", "dummy"))) + Expect(res).To(BeEmpty()) + }) + }) + + Context("select labels", func() { + It("selects label by name", func() { + res := Must(labelsel.Select(r3v2.Labels, labelsel.Name("l1"))) + Expect(res).To(Equal(v1.Labels{r3v2.Labels[0]})) + }) + + It("selects signed labels", func() { + res := Must(labelsel.Select(r3v2.Labels, labelsel.Signed())) + Expect(res).To(Equal(v1.Labels{r3v2.Labels[1]})) + }) + + It("selects no signed labels", func() { + res := Must(labelsel.Select(r1v2.Labels, labelsel.Signed())) + Expect(res).To(Equal(v1.Labels{})) + }) + + It("selects labels by or", func() { + res := Must(labelsel.Select(r3v2.Labels, labelsel.Or(labelsel.Name("l1"), labelsel.Version("v3")))) + Expect(res).To(Equal(v1.Labels{r3v2.Labels[0], r3v2.Labels[2]})) + }) + + It("selects labels by and", func() { + res := Must(labelsel.Select(r3v2.Labels, labelsel.And(labelsel.Value("labelvalue"), labelsel.Version("v2")))) + Expect(res).To(Equal(v1.Labels{r3v2.Labels[1]})) + }) + + It("selects labels by negated selector", func() { + res := Must(labelsel.Select(r3v2.Labels, labelsel.Not(labelsel.Value("labelvalue")))) + Expect(res).To(Equal(v1.Labels{r3v2.Labels[0]})) + }) + }) + }) + + Context("reference selection", func() { + cd := &compdesc.ComponentDescriptor{} + + r1v1 := compdesc.Reference{ + ElementMeta: compdesc.ElementMeta{ + Name: "r1", + Version: "v1", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"labelvalue\""), + Version: "v1", + Signing: false, + }, + }, + }, + ComponentName: "c1", + } + r1v2 := compdesc.Reference{ + ElementMeta: compdesc.ElementMeta{ + Name: "r1", + Version: "v2", + }, + ComponentName: "c1", + } + r2v1 := compdesc.Reference{ + ElementMeta: compdesc.ElementMeta{ + Name: "r2", + Version: "v1", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"othervalue\""), + Version: "v1", + Signing: false, + }, + }, + }, + ComponentName: "c2", + } + r3v2 := compdesc.Reference{ + ElementMeta: compdesc.ElementMeta{ + Name: "r3", + Version: "v2", + Labels: v1.Labels{ + v1.Label{ + Name: "l1", + Value: []byte("\"dummy\""), + Version: "v2", + Signing: false, + }, + v1.Label{ + Name: "l2", + Value: []byte("\"labelvalue\""), + Version: "v2", + Signing: true, + }, + v1.Label{ + Name: "l3", + Value: []byte("\"labelvalue\""), + Version: "v3", + }, + }, + }, + ComponentName: "c3", + } + + r4v3 := compdesc.Reference{ + ElementMeta: compdesc.ElementMeta{ + Name: "r4", + Version: "v3", + ExtraIdentity: v1.Identity{ + "extra": "value", + "other": "othervalue", + }, + }, + ComponentName: "c4", + } + + cd.References = compdesc.References{ + r1v1, + r1v2, + r2v1, + r3v2, + r4v3, + } + + Context("id selection", func() { + It("selects by name", func() { + res := Must(cd.SelectReferences(refsel.Name("r1"))) + Expect(res).To(Equal(compdesc.References{r1v1, r1v2})) + }) + + It("selects by version", func() { + res := Must(cd.SelectReferences(refsel.Version("v1"))) + Expect(res).To(Equal(compdesc.References{r1v1, r2v1})) + }) + + It("selects by version", func() { + res := Must(cd.SelectReferences(refsel.ExtraIdentityByKeyPairs("version", "v1"))) + Expect(res).To(Equal(compdesc.References{r1v1})) // no r2v1: version not part of identity + }) + }) + + Context("attr selection", func() { + It("selects by name", func() { + res := Must(cd.SelectReferences(refsel.Name("r1"))) + Expect(res).To(Equal(compdesc.References{r1v1, r1v2})) + }) + It("selects by version", func() { + res := Must(cd.SelectReferences(refsel.Version("v1"))) + Expect(res).To(Equal(compdesc.References{r1v1, r2v1})) + }) + It("selects by component", func() { + res := Must(cd.SelectReferences(refsel.Component("c2"))) + Expect(res).To(Equal(compdesc.References{r2v1})) + }) + + It("selects by label name", func() { + res := Must(cd.SelectReferences(refsel.LabelName("l1"))) + Expect(res).To(Equal(compdesc.References{r1v1, r2v1, r3v2})) + }) + It("selects by label version", func() { + res := Must(cd.SelectReferences(refsel.LabelVersion("v2"))) + Expect(res).To(Equal(compdesc.References{r3v2})) + }) + It("selects by label value", func() { + res := Must(cd.SelectReferences(refsel.LabelValue("labelvalue"))) + Expect(res).To(Equal(compdesc.References{r1v1, r3v2})) + }) + It("selects unrelated by label name and value", func() { + res := Must(cd.SelectReferences(refsel.LabelName("l1"), refsel.LabelValue("labelvalue"))) + Expect(res).To(Equal(compdesc.References{r1v1, r3v2})) // unrelated checks at resource level + }) + It("selects related by label name and value", func() { + res := Must(cd.SelectReferences(refsel.Label(labelsel.Name("l1"), labelsel.Value("labelvalue")))) + Expect(res).To(Equal(compdesc.References{r1v1})) // related checks at label level + }) + It("selects by signed label", func() { + res := Must(cd.SelectReferences(labelsel.Signed())) + Expect(res).To(Equal(compdesc.References{r3v2})) + }) + + It("selects with extra identity", func() { + res := Must(cd.SelectReferences(refsel.ExtraIdentityByKeyPairs("extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.References{r4v3})) + }) + + It("selects none with wrong extra identity value", func() { + res := Must(cd.SelectReferences(refsel.ExtraIdentityByKeyPairs("extra", "other"))) + Expect(res).To(BeEmpty()) + }) + + It("selects none with wrong extra identity key", func() { + res := Must(cd.SelectReferences(refsel.ExtraIdentityByKeyPairs("extra2", "value"))) + Expect(res).To(BeEmpty()) + }) + + It("selects by or", func() { + res := Must(cd.SelectReferences(refsel.Or(refsel.Name("r3"), refsel.Version("v2")))) + Expect(res).To(Equal(compdesc.References{r1v2, r3v2})) + }) + + It("selects by and", func() { + res := Must(cd.SelectReferences(refsel.And(refsel.Name("r1"), refsel.Version("v1")))) + Expect(res).To(Equal(compdesc.References{r1v1})) + }) + + It("selects by negated selector", func() { + res := Must(cd.SelectReferences(refsel.Not(refsel.Name("r1")))) + Expect(res).To(Equal(compdesc.References{r2v1, r3v2, r4v3})) + }) + + It("selects by identity selector", func() { + res := Must(cd.SelectReferences(refsel.IdentityByKeyPairs("r4", "extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.References{r4v3})) + }) + It("selects none by identity selector with missing attribute", func() { + res := Must(cd.SelectReferences(refsel.IdentityByKeyPairs("r4", "extra", "value"))) + Expect(res).To(BeEmpty()) + }) + + It("selects by partial identity selector", func() { + res := Must(cd.SelectReferences(refsel.PartialIdentityByKeyPairs("name", "r4", "extra", "value", "other", "othervalue"))) + Expect(res).To(Equal(compdesc.References{r4v3})) + }) + It("selects by partial identity selector with partial attributes", func() { + res := Must(cd.SelectReferences(refsel.PartialIdentityByKeyPairs("name", "r4", "extra", "value"))) + Expect(res).To(Equal(compdesc.References{r4v3})) + }) + It("selects none by partial identity selector with missing attribute", func() { + res := Must(cd.SelectReferences(refsel.IdentityByKeyPairs("r4", "extra", "value", "dummy", "dummy"))) + Expect(res).To(BeEmpty()) + }) + }) + }) +}) diff --git a/api/ocm/compdesc/selectors.go b/api/ocm/compdesc/selectors.go index 0e079d3ec4..eb52c6b4e2 100644 --- a/api/ocm/compdesc/selectors.go +++ b/api/ocm/compdesc/selectors.go @@ -8,6 +8,7 @@ import ( v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" resourcetypes "ocm.software/ocm/api/ocm/extensions/artifacttypes" "ocm.software/ocm/api/ocm/extraid" + "ocm.software/ocm/api/ocm/selectors/accessors" "ocm.software/ocm/api/utils" "ocm.software/ocm/api/utils/selector" ) @@ -171,7 +172,7 @@ func (b *withExtraId) Match(obj map[string]string) (bool, error) { } func (b *withExtraId) MatchElement(obj ElementSelectionContext) (bool, error) { - return b.Match(obj.ExtraIdentity) + return b.Match(obj.GetExtraIdentity()) } func (b *withExtraId) MatchResource(obj ResourceSelectionContext) (bool, error) { @@ -409,7 +410,7 @@ type byLabel struct { var _ LabelBasedSelector = (*byLabel)(nil) func (b *byLabel) MatchElement(obj ElementSelectionContext) (bool, error) { - return b.MatchLabels(obj.Labels) + return b.MatchLabels(obj.GetLabels()) } func (b *byLabel) MatchResource(obj ResourceSelectionContext) (bool, error) { @@ -552,7 +553,7 @@ func MatchReferencesByReferenceSelector(obj ReferenceSelectionContext, resourceS //////////////////////////////////////////////////////////////////////////////// type elementSelectionContext struct { - *ElementMeta + accessors.ElementMeta identity } @@ -560,7 +561,7 @@ type elementSelectionContext struct { type ElementSelectionContext = *elementSelectionContext // Deprecated: not supported anymore. -func NewElementSelectionContext(index int, elems ElementAccessor) ElementSelectionContext { +func NewElementSelectionContext(index int, elems ElementListAccessor) ElementSelectionContext { return &elementSelectionContext{ ElementMeta: elems.Get(index).GetMeta(), identity: identity{ @@ -672,7 +673,7 @@ func ByComponent(name string) ReferenceSelector { type identity struct { identity v1.Identity - accessor ElementAccessor + accessor ElementListAccessor index int } diff --git a/api/ocm/compdesc/util.go b/api/ocm/compdesc/util.go index f8995e2cee..f16503f3d9 100644 --- a/api/ocm/compdesc/util.go +++ b/api/ocm/compdesc/util.go @@ -37,7 +37,7 @@ func Validate(desc *ComponentDescriptor) error { // ElementIndex determines the index of an element in the element list // for a given ElementMeta. If no element is found -1 is returned. -func ElementIndex(acc ElementAccessor, metaprovider ElementMetaProvider) int { +func ElementIndex(acc ElementListAccessor, metaprovider ElementMetaProvider) int { meta := metaprovider.GetMeta() id := meta.GetIdentityDigest(acc) for i := 0; i < acc.Len(); i++ { diff --git a/api/ocm/cpi/repocpi/view_cv.go b/api/ocm/cpi/repocpi/view_cv.go index 0320314fe7..f2fed393dd 100644 --- a/api/ocm/cpi/repocpi/view_cv.go +++ b/api/ocm/cpi/repocpi/view_cv.go @@ -570,7 +570,7 @@ func (c *componentVersionAccessView) SetReference(ref *cpi.ComponentReference, o }) } -func (c *componentVersionAccessView) getElementIndex(kind string, acc compdesc.ElementAccessor, prov compdesc.ElementMetaProvider, optlist ...cpi.TargetOption) (int, error) { +func (c *componentVersionAccessView) getElementIndex(kind string, acc compdesc.ElementListAccessor, prov compdesc.ElementMetaProvider, optlist ...cpi.TargetOption) (int, error) { opts := internal.NewTargetOptions(optlist...) curidx := compdesc.ElementIndex(acc, prov) meta := prov.GetMeta() @@ -582,7 +582,7 @@ func (c *componentVersionAccessView) getElementIndex(kind string, acc compdesc.E return idx, err } if idx == -1 && curidx >= 0 { - if meta.Version == acc.Get(curidx).GetMeta().Version { + if meta.GetVersion() == acc.Get(curidx).GetMeta().GetVersion() { return -1, fmt.Errorf("adding a new %s with same base identity requires different version", kind) } } @@ -655,12 +655,13 @@ func (c *componentVersionAccessView) SelectResources(sel ...rscsel.Selector) ([] list := compdesc.MapToSelectorElementList(c.GetDescriptor().Resources) result := []cpi.ResourceAccess{} +outer: for _, r := range c.GetDescriptor().Resources { if len(sel) > 0 { mr := compdesc.MapToSelectorResource(&r) for _, s := range sel { if !s.MatchResource(list, mr) { - continue + continue outer } } } @@ -769,12 +770,13 @@ func (c *componentVersionAccessView) SelectSources(sel ...srcsel.Selector) ([]cp list := compdesc.MapToSelectorElementList(c.GetDescriptor().Sources) result := []cpi.SourceAccess{} +outer: for _, r := range c.GetDescriptor().Sources { if len(sel) > 0 { mr := compdesc.MapToSelectorSource(&r) for _, s := range sel { if !s.MatchSource(list, mr) { - continue + continue outer } } } diff --git a/api/ocm/internal/modopts.go b/api/ocm/internal/modopts.go index 98f902d727..841b12d5e3 100644 --- a/api/ocm/internal/modopts.go +++ b/api/ocm/internal/modopts.go @@ -7,6 +7,7 @@ import ( "ocm.software/ocm/api/ocm/compdesc" v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" + "ocm.software/ocm/api/ocm/selectors/accessors" "ocm.software/ocm/api/utils" ) @@ -94,7 +95,7 @@ func UseBlobHandlers(h BlobHandlerProvider) BlobOptionImpl { // resource or source for the SetXXX calls. // If -1 is returned an append is enforced. type TargetElement interface { - GetTargetIndex(resources compdesc.ElementAccessor, meta *compdesc.ElementMeta) (int, error) + GetTargetIndex(resources compdesc.ElementListAccessor, meta accessors.ElementMeta) (int, error) } type TargetOptionImpl interface { @@ -224,7 +225,7 @@ func NewModificationOptions(list ...ModificationOption) *ModificationOptions { type TargetIndex int -func (m TargetIndex) GetTargetIndex(elems compdesc.ElementAccessor, meta *compdesc.ElementMeta) (int, error) { +func (m TargetIndex) GetTargetIndex(elems compdesc.ElementListAccessor, meta accessors.ElementMeta) (int, error) { if int(m) >= elems.Len() { return -1, nil } @@ -247,7 +248,7 @@ func (m TargetIndex) ApplyTargetOption(opts *TargetOptions) { type TargetIdentityOrAppend v1.Identity -func (m TargetIdentityOrAppend) GetTargetIndex(elems compdesc.ElementAccessor, meta *compdesc.ElementMeta) (int, error) { +func (m TargetIdentityOrAppend) GetTargetIndex(elems compdesc.ElementListAccessor, meta accessors.ElementMeta) (int, error) { idx, _ := TargetIdentity(m).GetTargetIndex(elems, meta) return idx, nil } @@ -268,7 +269,7 @@ func (m TargetIdentityOrAppend) ApplyTargetOption(opts *TargetOptions) { type TargetIdentity v1.Identity -func (m TargetIdentity) GetTargetIndex(elems compdesc.ElementAccessor, meta *compdesc.ElementMeta) (int, error) { +func (m TargetIdentity) GetTargetIndex(elems compdesc.ElementListAccessor, meta accessors.ElementMeta) (int, error) { for i := 0; i < elems.Len(); i++ { r := elems.Get(i) if r.GetMeta().GetIdentity(elems).Equals(v1.Identity(m)) { @@ -296,7 +297,7 @@ type replaceElement struct{} var UpdateElement = replaceElement{} -func (m replaceElement) GetTargetIndex(elems compdesc.ElementAccessor, meta *compdesc.ElementMeta) (int, error) { +func (m replaceElement) GetTargetIndex(elems compdesc.ElementListAccessor, meta accessors.ElementMeta) (int, error) { id := meta.GetIdentity(elems) for i := 0; i < elems.Len(); i++ { if elems.Get(i).GetMeta().GetIdentity(elems).Equals(id) { diff --git a/api/ocm/ocmutils/check/check.go b/api/ocm/ocmutils/check/check.go index e1153a0d7c..232fafb649 100644 --- a/api/ocm/ocmutils/check/check.go +++ b/api/ocm/ocmutils/check/check.go @@ -128,7 +128,7 @@ func (a *Options) handle(cache Cache, cv ocm.ComponentVersionAccess, h common.Hi return result, list.Result() } -func (a *Options) checkArtifacts(ctx ocm.Context, accessor compdesc.ElementAccessor) ([]metav1.Identity, error) { +func (a *Options) checkArtifacts(ctx ocm.Context, accessor compdesc.ElementListAccessor) ([]metav1.Identity, error) { var result []metav1.Identity list := errors.ErrorList{} diff --git a/api/ocm/selectors/accessors/accessors.go b/api/ocm/selectors/accessors/accessors.go index dcc9f989f1..fa8b776487 100644 --- a/api/ocm/selectors/accessors/accessors.go +++ b/api/ocm/selectors/accessors/accessors.go @@ -1,6 +1,7 @@ package accessors import ( + "ocm.software/ocm/api/ocm/compdesc/equivalent" v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" "ocm.software/ocm/api/utils/runtime" ) @@ -8,7 +9,7 @@ import ( // ElementListAccessor provides generic access to list of elements. type ElementListAccessor interface { Len() int - Get(i int) ElementMetaAccessor + Get(i int) Element } // ElementMeta describes the access to common element meta data attributes. @@ -17,14 +18,30 @@ type ElementMeta interface { GetVersion() string GetExtraIdentity() v1.Identity GetLabels() v1.Labels - GetIdentityForContext(accessor ElementListAccessor) v1.Identity + GetIdentity(accessor ElementListAccessor) v1.Identity + GetIdentityDigest(accessor ElementListAccessor) []byte + + GetRawIdentity() v1.Identity + GetMatchBaseIdentity() v1.Identity + + GetMeta() ElementMeta // ElementMeta is again a Meta provider + + SetLabels(labels []v1.Label) } -// ElementMetaAccessor provides generic access an elements meta information. -type ElementMetaAccessor interface { +// ElementMetaProvider just provides access to element meta data +// of an element. +type ElementMetaProvider interface { GetMeta() ElementMeta } +// Element represents a generic element with meta information. +// It also allows to check for equivalence of elements of the same kind. +type Element interface { + ElementMetaProvider + Equivalent(Element) equivalent.EqualState +} + // AccessSpec is the minimal interface for access spec attributes. type AccessSpec interface { runtime.VersionedTypedObject @@ -32,7 +49,7 @@ type AccessSpec interface { // ArtifactAccessor provides access to generic artifact information of an element. type ArtifactAccessor interface { - ElementMetaAccessor + Element GetType() string GetAccess() AccessSpec } @@ -51,6 +68,6 @@ type SourceAccessor interface { // ReferenceAccessor provides access to source attribute. type ReferenceAccessor interface { - ElementMetaAccessor + Element GetComponentName() string } diff --git a/api/ocm/selectors/identity.go b/api/ocm/selectors/identity.go index 01b517cf28..1e6a882ac2 100644 --- a/api/ocm/selectors/identity.go +++ b/api/ocm/selectors/identity.go @@ -18,15 +18,15 @@ type IdentitySelectorImpl struct { } func (i *IdentitySelectorImpl) MatchResource(list accessors.ElementListAccessor, a accessors.ResourceAccessor) bool { - return i.MatchIdentity(a.GetMeta().GetIdentityForContext(list)) + return i.MatchIdentity(a.GetMeta().GetIdentity(list)) } func (i *IdentitySelectorImpl) MatchSource(list accessors.ElementListAccessor, a accessors.SourceAccessor) bool { - return i.MatchIdentity(a.GetMeta().GetIdentityForContext(list)) + return i.MatchIdentity(a.GetMeta().GetIdentity(list)) } func (i *IdentitySelectorImpl) MatchReference(list accessors.ElementListAccessor, a accessors.ReferenceAccessor) bool { - return i.MatchIdentity(a.GetMeta().GetIdentityForContext(list)) + return i.MatchIdentity(a.GetMeta().GetIdentity(list)) } type IdentityErrorSelectorImpl struct { @@ -79,8 +79,8 @@ func (i *id) MatchIdentity(identity v1.Identity) bool { return true } -func IdentityByKeyPairs(extra ...string) *IdentitySelectorImpl { - return &IdentitySelectorImpl{&id{v1.NewExtraIdentity(extra...)}} +func IdentityByKeyPairs(name string, extra ...string) *IdentitySelectorImpl { + return &IdentitySelectorImpl{&id{v1.NewIdentity(name, extra...)}} } func Identity(identity v1.Identity) *IdentitySelectorImpl { @@ -89,6 +89,57 @@ func Identity(identity v1.Identity) *IdentitySelectorImpl { //////////////////////////////////////////////////////////////////////////////// +type extraid struct { + v1.Identity +} + +func (i *extraid) MatchIdentity(identity v1.Identity) bool { + identity = identity.ExtraIdentity() + + if len(i.Identity) != len(identity) { + return false + } + for n, v := range i.Identity { + if identity[n] != v { + return false + } + } + return true +} + +func ExtraIdentityByKeyPairs(extra ...string) *IdentitySelectorImpl { + return &IdentitySelectorImpl{&extraid{v1.NewExtraIdentity(extra...)}} +} + +func ExtraIdentity(identity v1.Identity) *IdentitySelectorImpl { + return &IdentitySelectorImpl{&extraid{identity}} +} + +//////////////////////////////////////////////////////////////////////////////// + +type partialid struct { + v1.Identity +} + +func (i *partialid) MatchIdentity(identity v1.Identity) bool { + for n, v := range i.Identity { + if identity[n] != v { + return false + } + } + return true +} + +func PartialIdentityByKeyPairs(attrs ...string) *IdentitySelectorImpl { + return &IdentitySelectorImpl{&partialid{v1.NewExtraIdentity(attrs...)}} +} + +func PartialIdentity(identity v1.Identity) *IdentitySelectorImpl { + return &IdentitySelectorImpl{&partialid{identity}} +} + +//////////////////////////////////////////////////////////////////////////////// + type num int func (i num) MatchIdentity(identity v1.Identity) bool { diff --git a/api/ocm/selectors/label.go b/api/ocm/selectors/label.go index 92f2574ce3..2b3fd43f0b 100644 --- a/api/ocm/selectors/label.go +++ b/api/ocm/selectors/label.go @@ -13,12 +13,13 @@ func SelectLabels(labels v1.Labels, sel ...LabelSelector) ([]v1.Label, error) { return GetLabels(labels, sel...), nil } -func GetLabels(labels v1.Labels, sel ...LabelSelector) []v1.Label { - var result []v1.Label +func GetLabels(labels v1.Labels, sel ...LabelSelector) v1.Labels { + result := v1.Labels{} +outer: for _, l := range labels { for _, s := range sel { if !s.MatchLabel(&l) { - continue + continue outer } } result = append(result, l) diff --git a/api/ocm/selectors/labelsel/interface.go b/api/ocm/selectors/labelsel/interface.go index 823b4f97e7..d333562dd1 100644 --- a/api/ocm/selectors/labelsel/interface.go +++ b/api/ocm/selectors/labelsel/interface.go @@ -23,11 +23,11 @@ func init() { type Selector = selectors.LabelSelector -func Select(labels v1.Labels, sel ...Selector) ([]v1.Label, error) { +func Select(labels v1.Labels, sel ...Selector) (v1.Labels, error) { return selectors.SelectLabels(labels, sel...) } -func Get(labels v1.Labels, sel ...Selector) []v1.Label { +func Get(labels v1.Labels, sel ...Selector) v1.Labels { return selectors.GetLabels(labels, sel...) } diff --git a/api/ocm/selectors/refsel/element.go b/api/ocm/selectors/refsel/element.go index cf77bc7bf9..8998c8e81e 100644 --- a/api/ocm/selectors/refsel/element.go +++ b/api/ocm/selectors/refsel/element.go @@ -8,14 +8,30 @@ import ( // Identity selectors -func IdentityByKeyPairs(extras ...string) Selector { - return selectors.IdentityByKeyPairs(extras...) +func IdentityByKeyPairs(name string, extras ...string) Selector { + return selectors.IdentityByKeyPairs(name, extras...) } func Identity(id v1.Identity) Selector { return selectors.Identity(id) } +func ExtraIdentity(id v1.Identity) Selector { + return selectors.ExtraIdentity(id) +} + +func ExtraIdentityByKeyPairs(extra ...string) Selector { + return selectors.ExtraIdentityByKeyPairs(extra...) +} + +func Partialdentity(id v1.Identity) Selector { + return selectors.PartialIdentity(id) +} + +func PartialIdentityByKeyPairs(attrs ...string) Selector { + return selectors.PartialIdentityByKeyPairs(attrs...) +} + func Name(n string) Selector { return selectors.Name(n) } @@ -33,3 +49,11 @@ func Label(sel ...selectors.LabelSelector) Selector { func LabelName(n string) Selector { return labelsel.Name(n) } + +func LabelVersion(n string) Selector { + return labelsel.Version(n) +} + +func LabelValue(v interface{}) Selector { + return labelsel.Value(v) +} diff --git a/api/ocm/selectors/rscsel/artifact.go b/api/ocm/selectors/rscsel/artifact.go index 5995e19f6b..db03d5dd79 100644 --- a/api/ocm/selectors/rscsel/artifact.go +++ b/api/ocm/selectors/rscsel/artifact.go @@ -10,6 +10,10 @@ func ArtifactType(n string) Selector { return selectors.ArtifactType(n) } +func ResourceType(n string) Selector { + return selectors.ArtifactType(n) +} + func AccessKind(n string) Selector { return selectors.AccessKind(n) } diff --git a/api/ocm/selectors/rscsel/element.go b/api/ocm/selectors/rscsel/element.go index 28b2391474..4ecc636efd 100644 --- a/api/ocm/selectors/rscsel/element.go +++ b/api/ocm/selectors/rscsel/element.go @@ -8,14 +8,30 @@ import ( // Identity selectors -func IdentityByKeyPairs(extras ...string) Selector { - return selectors.IdentityByKeyPairs(extras...) +func IdentityByKeyPairs(name string, extras ...string) Selector { + return selectors.IdentityByKeyPairs(name, extras...) } func Identity(id v1.Identity) Selector { return selectors.Identity(id) } +func ExtraIdentity(id v1.Identity) Selector { + return selectors.ExtraIdentity(id) +} + +func ExtraIdentityByKeyPairs(extra ...string) Selector { + return selectors.ExtraIdentityByKeyPairs(extra...) +} + +func Partialdentity(id v1.Identity) Selector { + return selectors.PartialIdentity(id) +} + +func PartialIdentityByKeyPairs(attrs ...string) Selector { + return selectors.PartialIdentityByKeyPairs(attrs...) +} + func Name(n string) Selector { return selectors.Name(n) } @@ -37,3 +53,11 @@ func Label(sel ...selectors.LabelSelector) Selector { func LabelName(n string) Selector { return labelsel.Name(n) } + +func LabelVersion(n string) Selector { + return labelsel.Version(n) +} + +func LabelValue(v interface{}) Selector { + return labelsel.Value(v) +} diff --git a/api/ocm/selectors/select.go b/api/ocm/selectors/select.go index e125017d2e..41f9c6ccb9 100644 --- a/api/ocm/selectors/select.go +++ b/api/ocm/selectors/select.go @@ -129,11 +129,12 @@ func validateSelectors[T any](list *errors.ErrorList, sel ...T) error { func _select[S, E any](list accessors.ElementListAccessor, m func(S, E) bool, sel ...S) []E { var result []E +outer: for i := 0; i < list.Len(); i++ { e := list.Get(i).(E) for _, s := range sel { if !m(s, e) { - continue + continue outer } } result = append(result, e) diff --git a/api/ocm/selectors/srcsel/artifact.go b/api/ocm/selectors/srcsel/artifact.go index 353fcb100c..0342d1edc9 100644 --- a/api/ocm/selectors/srcsel/artifact.go +++ b/api/ocm/selectors/srcsel/artifact.go @@ -10,6 +10,10 @@ func ArtifactType(n string) Selector { return selectors.ArtifactType(n) } +func SourceType(n string) Selector { + return selectors.ArtifactType(n) +} + func AccessKind(n string) Selector { return selectors.AccessKind(n) } diff --git a/api/ocm/selectors/srcsel/element.go b/api/ocm/selectors/srcsel/element.go index ff45ea1dd1..fb1989d0fc 100644 --- a/api/ocm/selectors/srcsel/element.go +++ b/api/ocm/selectors/srcsel/element.go @@ -8,14 +8,30 @@ import ( // Identity selectors -func IdentityByKeyPairs(extras ...string) Selector { - return selectors.IdentityByKeyPairs(extras...) +func IdentityByKeyPairs(name string, extras ...string) Selector { + return selectors.IdentityByKeyPairs(name, extras...) } func Identity(id v1.Identity) Selector { return selectors.Identity(id) } +func ExtraIdentity(id v1.Identity) Selector { + return selectors.ExtraIdentity(id) +} + +func ExtraIdentityByKeyPairs(extra ...string) Selector { + return selectors.ExtraIdentityByKeyPairs(extra...) +} + +func Partialdentity(id v1.Identity) Selector { + return selectors.PartialIdentity(id) +} + +func PartialIdentityByKeyPairs(attrs ...string) Selector { + return selectors.PartialIdentityByKeyPairs(attrs...) +} + func Name(n string) Selector { return selectors.Name(n) } @@ -37,3 +53,11 @@ func Label(sel ...selectors.LabelSelector) Selector { func LabelName(n string) Selector { return labelsel.Name(n) } + +func LabelVersion(n string) Selector { + return labelsel.Version(n) +} + +func LabelValue(v interface{}) Selector { + return labelsel.Value(v) +} diff --git a/api/ocm/tools/transfer/internal/merge.go b/api/ocm/tools/transfer/internal/merge.go index 635a239835..9307aa1496 100644 --- a/api/ocm/tools/transfer/internal/merge.go +++ b/api/ocm/tools/transfer/internal/merge.go @@ -43,15 +43,17 @@ func PrepareDescriptor(log logging.Logger, ctx ocm.Context, s *compdesc.Componen return n, nil } -func MergeElements(log logging.Logger, ctx ocm.Context, s compdesc.ElementAccessor, t compdesc.ElementAccessor) error { +func MergeElements(log logging.Logger, ctx ocm.Context, s compdesc.ElementListAccessor, t compdesc.ElementListAccessor) error { for i := 0; i < s.Len(); i++ { es := s.Get(i) id := es.GetMeta().GetIdentity(s) et := compdesc.GetByIdentity(t, id) if et != nil { - if err := MergeLabels(log, ctx, es.GetMeta().Labels, &et.GetMeta().Labels); err != nil { + labels := et.GetMeta().GetLabels() + if err := MergeLabels(log, ctx, es.GetMeta().GetLabels(), &labels); err != nil { return err } + et.GetMeta().SetLabels(labels) // keep access for same digest if aes, ok := es.(compdesc.ElementArtifactAccessor); ok { diff --git a/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/output.go b/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/output.go index 4656ad508e..8a8a74d200 100644 --- a/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/output.go +++ b/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/output.go @@ -17,7 +17,7 @@ func MapMetaOutput(e interface{}) []string { m := p.Element.GetMeta() id := p.Id.Copy() id.Remove(metav1.SystemIdentityName) - return []string{m.Name, m.Version, id.String()} + return []string{m.GetName(), m.GetVersion(), id.String()} } func MapNodeOutput(e interface{}) []string { diff --git a/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/typehandler.go b/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/typehandler.go index a6631821ce..6e960c30c7 100644 --- a/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/typehandler.go +++ b/cmds/ocm/commands/ocmcmds/common/handlers/elemhdlr/typehandler.go @@ -37,8 +37,8 @@ var ( ) type Manifest struct { - History common.History `json:"context"` - Element compdesc.ElementMetaAccessor `json:"element"` + History common.History `json:"context"` + Element compdesc.Element `json:"element"` } func (o *Object) AsManifest() interface{} { @@ -90,10 +90,10 @@ type TypeHandler struct { kind string forceEmpty bool filter ElementFilter - elemaccess func(ocm.ComponentVersionAccess) compdesc.ElementAccessor + elemaccess func(ocm.ComponentVersionAccess) compdesc.ElementListAccessor } -func NewTypeHandler(octx clictx.OCM, oopts *output.Options, repobase ocm.Repository, session ocm.Session, kind string, compspecs []string, elemaccess func(ocm.ComponentVersionAccess) compdesc.ElementAccessor, hopts ...Option) (utils.TypeHandler, error) { +func NewTypeHandler(octx clictx.OCM, oopts *output.Options, repobase ocm.Repository, session ocm.Session, kind string, compspecs []string, elemaccess func(ocm.ComponentVersionAccess) compdesc.ElementListAccessor, hopts ...Option) (utils.TypeHandler, error) { components, err := comphdlr.Evaluate(octx, session, repobase, compspecs, oopts, MapToCompHandlerOptions(hopts...)...) if err != nil { return nil, err diff --git a/cmds/ocm/commands/ocmcmds/common/resources.go b/cmds/ocm/commands/ocmcmds/common/resources.go index ff8c16c964..0517c7b486 100644 --- a/cmds/ocm/commands/ocmcmds/common/resources.go +++ b/cmds/ocm/commands/ocmcmds/common/resources.go @@ -85,7 +85,7 @@ func checkHint(v ocm.ComponentVersionAccess, typ string, elem addhdlrs.Element, } if mime.BaseType(local.MediaType) == mime.BaseType(olocal.MediaType) { return fmt.Errorf("reference name (hint) %q with base media type %s already used for %s %s:%s", - local.ReferenceName, mime.BaseType(local.MediaType), typ, a.GetMeta().Name, a.GetMeta().Version) + local.ReferenceName, mime.BaseType(local.MediaType), typ, a.GetMeta().GetName(), a.GetMeta().GetVersion()) } } return nil diff --git a/cmds/ocm/commands/ocmcmds/references/add/cmd_test.go b/cmds/ocm/commands/ocmcmds/references/add/cmd_test.go index db064e9f32..e712f01ef1 100644 --- a/cmds/ocm/commands/ocmcmds/references/add/cmd_test.go +++ b/cmds/ocm/commands/ocmcmds/references/add/cmd_test.go @@ -5,6 +5,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "ocm.software/ocm/api/ocm/selectors/refsel" . "ocm.software/ocm/cmds/ocm/testhelper" "github.com/mandelsoft/goutils/testutils" @@ -21,7 +22,7 @@ const ( ) func CheckReference(env *TestEnv, cd *compdesc.ComponentDescriptor, name string, add ...func(compdesc.Reference)) { - rs, _ := cd.GetReferencesByName(name) + rs, _ := cd.SelectReferences(refsel.Name(name)) if len(rs) != 1 { Fail(fmt.Sprintf("%d reference(s) with name %s found", len(rs), name), 1) } diff --git a/cmds/ocm/commands/ocmcmds/references/common/typehandler.go b/cmds/ocm/commands/ocmcmds/references/common/typehandler.go index 4adeb7a00c..325a057722 100644 --- a/cmds/ocm/commands/ocmcmds/references/common/typehandler.go +++ b/cmds/ocm/commands/ocmcmds/references/common/typehandler.go @@ -22,7 +22,7 @@ type TypeHandler struct { } func NewTypeHandler(octx clictx.OCM, opts *output.Options, repo ocm.Repository, session ocm.Session, compspecs []string, hopts ...elemhdlr.Option) (utils.TypeHandler, error) { - return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_REFERENCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementAccessor { + return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_REFERENCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementListAccessor { return access.GetDescriptor().References }, hopts...) } diff --git a/cmds/ocm/commands/ocmcmds/resources/common/typehandler.go b/cmds/ocm/commands/ocmcmds/resources/common/typehandler.go index 648463d3c1..6e729dc60c 100644 --- a/cmds/ocm/commands/ocmcmds/resources/common/typehandler.go +++ b/cmds/ocm/commands/ocmcmds/resources/common/typehandler.go @@ -49,7 +49,7 @@ func WithTypes(types []string) elemhdlr.Option { //////////////////////////////////////////////////////////////////////////////// func NewTypeHandler(octx clictx.OCM, opts *output.Options, repo ocm.Repository, session ocm.Session, compspecs []string, hopts ...elemhdlr.Option) (utils.TypeHandler, error) { - return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_RESOURCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementAccessor { + return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_RESOURCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementListAccessor { return access.GetDescriptor().Resources }, hopts...) } diff --git a/cmds/ocm/commands/ocmcmds/sources/common/typehandler.go b/cmds/ocm/commands/ocmcmds/sources/common/typehandler.go index 1442c6dbb9..9b960ad6dc 100644 --- a/cmds/ocm/commands/ocmcmds/sources/common/typehandler.go +++ b/cmds/ocm/commands/ocmcmds/sources/common/typehandler.go @@ -22,7 +22,7 @@ type TypeHandler struct { } func NewTypeHandler(octx clictx.OCM, opts *output.Options, repo ocm.Repository, session ocm.Session, compspecs []string, hopts ...elemhdlr.Option) (utils.TypeHandler, error) { - return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_SOURCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementAccessor { + return elemhdlr.NewTypeHandler(octx, opts, repo, session, ocm.KIND_SOURCE, compspecs, func(access ocm.ComponentVersionAccess) compdesc.ElementListAccessor { return access.GetDescriptor().Sources }, hopts...) } diff --git a/examples/lib/comparison-scenario/09-localize.go b/examples/lib/comparison-scenario/09-localize.go index 4307a5df71..a61b595539 100644 --- a/examples/lib/comparison-scenario/09-localize.go +++ b/examples/lib/comparison-scenario/09-localize.go @@ -8,10 +8,10 @@ import ( "github.com/mandelsoft/vfs/pkg/memoryfs" "github.com/mandelsoft/vfs/pkg/vfs" "helm.sh/helm/v3/pkg/chart" + "ocm.software/ocm/api/ocm/selectors/rscsel" "sigs.k8s.io/yaml" "ocm.software/ocm/api/ocm" - "ocm.software/ocm/api/ocm/compdesc" v1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" "ocm.software/ocm/api/ocm/extensions/download" "ocm.software/ocm/api/ocm/ocmutils" @@ -126,7 +126,7 @@ func Localize(cfg *helper.Config, config template.Values, release, namespace str } defer cv.Close() - res, err := cv.GetResourcesByResourceSelectors(compdesc.ByResourceType(DEPLOY_SCRIPT_TYPE)) + res, err := cv.SelectResources(rscsel.ArtifactType(DEPLOY_SCRIPT_TYPE)) if err != nil { return errors.Wrapf(err, "no deploy descriptor found") }