From 9c0582665ee89dcd3f2e9aacc9bebe4bfd583181 Mon Sep 17 00:00:00 2001 From: Tim Schrodi Date: Wed, 23 Jun 2021 16:05:56 +0200 Subject: [PATCH] add list resolver --- bindings-go/ctf/ctf.go | 4 ++ bindings-go/ctf/listresolver.go | 58 +++++++++++++++++ bindings-go/ctf/listresolver_test.go | 97 ++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 bindings-go/ctf/listresolver.go create mode 100644 bindings-go/ctf/listresolver_test.go diff --git a/bindings-go/ctf/ctf.go b/bindings-go/ctf/ctf.go index 9e52c42c..9c6ffe63 100644 --- a/bindings-go/ctf/ctf.go +++ b/bindings-go/ctf/ctf.go @@ -42,6 +42,10 @@ const BlobsDirectoryName = "blobs" var UnsupportedResolveType = errors.New("UnsupportedResolveType") +var NotFoundError = errors.New("ComponentDescriptorNotFound") + +var BlobResolverNotDefinedError = errors.New("BlobResolverNotDefined") + // ComponentResolver describes a general interface to resolve a component descriptor type ComponentResolver interface { Resolve(ctx context.Context, repoCtx v2.Repository, name, version string) (*v2.ComponentDescriptor, error) diff --git a/bindings-go/ctf/listresolver.go b/bindings-go/ctf/listresolver.go new file mode 100644 index 00000000..dd130fc7 --- /dev/null +++ b/bindings-go/ctf/listresolver.go @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2021 SAP SE or an SAP affiliate company and Gardener contributors. +// +// SPDX-License-Identifier: Apache-2.0 + +package ctf + +import ( + "context" + + cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" +) + +// ListResolver describes a ComponentResolver using a list of Component Descriptors +type ListResolver struct { + List *cdv2.ComponentDescriptorList + blobResolver *AggregatedBlobResolver +} + +// NewListResolver creates a new list resolver. +func NewListResolver(list *cdv2.ComponentDescriptorList, resolvers ...BlobResolver) (*ListResolver, error) { + lr := &ListResolver{ + List: list, + } + if len(resolvers) != 0 { + blobResolver, err := NewAggregatedBlobResolver(resolvers...) + if err != nil { + return nil, err + } + lr.blobResolver = blobResolver + } + return lr, nil +} + +var _ ComponentResolver = &ListResolver{} + +func (l ListResolver) Resolve(_ context.Context, repoCtx cdv2.Repository, name, version string) (*cdv2.ComponentDescriptor, error) { + for _, comp := range l.List.Components { + if !cdv2.TypedObjectEqual(repoCtx, comp.GetEffectiveRepositoryContext()) { + continue + } + if comp.Name == name && comp.Version == version { + return comp.DeepCopy(), nil + } + } + + return nil, NotFoundError +} + +func (l ListResolver) ResolveWithBlobResolver(ctx context.Context, repoCtx cdv2.Repository, name, version string) (*cdv2.ComponentDescriptor, BlobResolver, error) { + cd, err := l.Resolve(ctx, repoCtx, name, version) + if err != nil { + return nil, nil, err + } + if l.blobResolver == nil { + return nil, nil, BlobResolverNotDefinedError + } + return cd, l.blobResolver, err +} diff --git a/bindings-go/ctf/listresolver_test.go b/bindings-go/ctf/listresolver_test.go new file mode 100644 index 00000000..cb8bab1a --- /dev/null +++ b/bindings-go/ctf/listresolver_test.go @@ -0,0 +1,97 @@ +// Copyright 2021 Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ctf_test + +import ( + "context" + + cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" + "github.com/gardener/component-spec/bindings-go/ctf" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("ListResolver", func() { + + It("should resolve a component from a list of one component descriptor", func() { + cd := cdv2.ComponentDescriptor{} + cd.Name = "example.com/a" + cd.Version = "0.0.0" + repoCtx, _ := cdv2.NewUnstructured(cdv2.NewOCIRegistryRepository("example.com/registry", "")) + cd.RepositoryContexts = append(cd.RepositoryContexts, &repoCtx) + + lr, err := ctf.NewListResolver(&cdv2.ComponentDescriptorList{ + Components: []cdv2.ComponentDescriptor{cd}, + }) + Expect(err).ToNot(HaveOccurred()) + res, err := lr.Resolve(context.TODO(), &repoCtx, "example.com/a", "0.0.0") + Expect(err).ToNot(HaveOccurred()) + Expect(res.Name).To(Equal("example.com/a")) + }) + + It("should resolve a component from a list of multiple component descriptors", func() { + cd := cdv2.ComponentDescriptor{} + cd.Name = "example.com/a" + cd.Version = "0.0.0" + repoCtx, _ := cdv2.NewUnstructured(cdv2.NewOCIRegistryRepository("example.com/registry", "")) + cd.RepositoryContexts = append(cd.RepositoryContexts, &repoCtx) + + cd2 := cdv2.ComponentDescriptor{} + cd2.Name = "example.com/a" + cd2.Version = "0.0.0" + cd2.Labels = cdv2.Labels{ + { + Name: "test", + }, + } + repoCtx2, _ := cdv2.NewUnstructured(cdv2.NewOCIRegistryRepository("example.com/registry2", "")) + cd2.RepositoryContexts = append(cd.RepositoryContexts, &repoCtx2) + + lr, err := ctf.NewListResolver(&cdv2.ComponentDescriptorList{ + Components: []cdv2.ComponentDescriptor{cd, cd2}, + }) + Expect(err).ToNot(HaveOccurred()) + res, err := lr.Resolve(context.TODO(), &repoCtx2, "example.com/a", "0.0.0") + Expect(err).ToNot(HaveOccurred()) + Expect(res.Name).To(Equal("example.com/a")) + Expect(res.Labels).To(ContainElement(cdv2.Label{ + Name: "test", + })) + + res, err = lr.Resolve(context.TODO(), &repoCtx, "example.com/a", "0.0.0") + Expect(err).ToNot(HaveOccurred()) + Expect(res.Name).To(Equal("example.com/a")) + Expect(res.Labels).ToNot(ContainElement(cdv2.Label{ + Name: "test", + })) + }) + + It("should not resolve a component if the repository contexts do not match", func() { + cd := cdv2.ComponentDescriptor{} + cd.Name = "example.com/a" + cd.Version = "0.0.0" + repoCtx, _ := cdv2.NewUnstructured(cdv2.NewOCIRegistryRepository("example.com/registry", "")) + cd.RepositoryContexts = append(cd.RepositoryContexts, &repoCtx) + + lr, err := ctf.NewListResolver(&cdv2.ComponentDescriptorList{ + Components: []cdv2.ComponentDescriptor{cd}, + }) + Expect(err).ToNot(HaveOccurred()) + _, err = lr.Resolve(context.TODO(), &repoCtx, "example.com/b", "0.0.0") + Expect(err).To(HaveOccurred()) + Expect(err).To(Equal(ctf.NotFoundError)) + }) + +})