From e4b09b1aacbc18aab978358c51f7c5e7ecaa69cd Mon Sep 17 00:00:00 2001 From: Robert Graeff Date: Thu, 20 Jun 2024 13:31:45 +0200 Subject: [PATCH] Subinstallation context --- pkg/components/model/componentversion_refs.go | 6 --- pkg/landscaper/installations/context.go | 39 +++++++-------- pkg/landscaper/installations/context_test.go | 50 ++++++++----------- .../installations/executions/operation.go | 2 +- .../executions/operation_test.go | 10 ++-- .../installations/imports/constructor.go | 2 +- .../installations/subinstallations/helper.go | 12 ++++- .../subinstallations/subinstallations_test.go | 5 +- .../registry/components/cdutils/uri.go | 4 +- 9 files changed, 59 insertions(+), 71 deletions(-) diff --git a/pkg/components/model/componentversion_refs.go b/pkg/components/model/componentversion_refs.go index b3f608d6b3..e495e62246 100644 --- a/pkg/components/model/componentversion_refs.go +++ b/pkg/components/model/componentversion_refs.go @@ -6,7 +6,6 @@ package model import ( "context" - "errors" "fmt" "github.com/gardener/landscaper/controller-utils/pkg/logging" @@ -75,11 +74,6 @@ func getTransitiveComponentReferencesRecursively(ctx context.Context, } cds[cid] = cd - cdRepositoryContext := cd.GetRepositoryContext() - if cdRepositoryContext == nil { - return errors.New("component descriptor must at least contain one repository context with a base url") - } - cdComponentReferences := cd.GetComponentReferences() for _, compRef := range cdComponentReferences { diff --git a/pkg/landscaper/installations/context.go b/pkg/landscaper/installations/context.go index 3bc2493216..0631b11a8f 100644 --- a/pkg/landscaper/installations/context.go +++ b/pkg/landscaper/installations/context.go @@ -9,19 +9,18 @@ import ( "errors" "fmt" - "github.com/gardener/landscaper/pkg/utils" - + cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" + lsv1alpha1 "github.com/gardener/landscaper/apis/core/v1alpha1" + lsv1alpha1helper "github.com/gardener/landscaper/apis/core/v1alpha1/helper" lserrors "github.com/gardener/landscaper/apis/errors" kutil "github.com/gardener/landscaper/controller-utils/pkg/kubernetes" "github.com/gardener/landscaper/controller-utils/pkg/logging" - "github.com/gardener/landscaper/pkg/components/model/componentoverwrites" - - lsv1alpha1 "github.com/gardener/landscaper/apis/core/v1alpha1" - lsv1alpha1helper "github.com/gardener/landscaper/apis/core/v1alpha1/helper" lc "github.com/gardener/landscaper/controller-utils/pkg/logging/constants" + "github.com/gardener/landscaper/pkg/components/model/componentoverwrites" + "github.com/gardener/landscaper/pkg/utils" "github.com/gardener/landscaper/pkg/utils/read_write_layer" ) @@ -133,6 +132,9 @@ type ExternalContext struct { ComponentName string // ComponentVersion defines the version of the component. ComponentVersion string + // ResultingRepositoryContext is the repository context, taking into account the repository context in the + // installation, the repository context in the context resource, and the overwriter. + ResultingRepositoryContext *cdv2.UnstructuredTypedObject // Overwriter is the component version overwriter used for this installation. Overwriter componentoverwrites.Overwriter } @@ -143,7 +145,7 @@ func (c *ExternalContext) ComponentDescriptorRef() *lsv1alpha1.ComponentDescript return nil } ref := &lsv1alpha1.ComponentDescriptorReference{} - ref.RepositoryContext = c.RepositoryContext + ref.RepositoryContext = c.ResultingRepositoryContext ref.ComponentName = c.ComponentName ref.Version = c.ComponentVersion return ref @@ -232,15 +234,6 @@ func GetParent(ctx context.Context, kubeClient client.Client, inst *lsv1alpha1.I return parent, nil } -// GetInstallationContextName returns the name of the context of an installation. -// The context name is basically the name of the parent component. -func GetInstallationContextName(inst *lsv1alpha1.Installation) string { - if IsRootInstallation(inst) { - return "" - } - return lsv1alpha1helper.DataObjectSourceFromInstallationName(GetParentInstallationName(inst)) -} - // IsRoot returns if the current component is a root component func (o *Operation) IsRoot() bool { return o.Context().Parent == nil @@ -287,6 +280,9 @@ func GetExternalContext(ctx context.Context, kubeClient client.Client, inst *lsv }, nil } + // Avoid that component overwrite modifies the installation + cdRef = cdRef.DeepCopy() + cond, err := ApplyComponentOverwrite(ctx, inst, overwriter, lsCtx, cdRef) if err != nil { return ExternalContext{}, lserrors.NewWrappedError(err, @@ -298,12 +294,13 @@ func GetExternalContext(ctx context.Context, kubeClient client.Client, inst *lsv if cdRef.RepositoryContext == nil { return ExternalContext{}, MissingRepositoryContextError } - lsCtx.RepositoryContext = cdRef.RepositoryContext + //lsCtx.RepositoryContext = cdRef.RepositoryContext return ExternalContext{ - Context: *lsCtx, - ComponentName: cdRef.ComponentName, - ComponentVersion: cdRef.Version, - Overwriter: overwriter, + Context: *lsCtx, + ComponentName: cdRef.ComponentName, + ComponentVersion: cdRef.Version, + ResultingRepositoryContext: cdRef.RepositoryContext, + Overwriter: overwriter, }, nil } diff --git a/pkg/landscaper/installations/context_test.go b/pkg/landscaper/installations/context_test.go index e756d8b190..a7146cf46a 100644 --- a/pkg/landscaper/installations/context_test.go +++ b/pkg/landscaper/installations/context_test.go @@ -7,24 +7,20 @@ package installations_test import ( "context" - "github.com/open-component-model/ocm/pkg/contexts/datacontext" - "github.com/open-component-model/ocm/pkg/contexts/ocm" - - "github.com/gardener/landscaper/controller-utils/pkg/logging" - - "github.com/gardener/landscaper/apis/config" - cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gstruct" + "github.com/open-component-model/ocm/pkg/contexts/datacontext" + "github.com/open-component-model/ocm/pkg/contexts/ocm" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/gardener/landscaper/apis/config" lsv1alpha1 "github.com/gardener/landscaper/apis/core/v1alpha1" + "github.com/gardener/landscaper/controller-utils/pkg/logging" "github.com/gardener/landscaper/pkg/api" "github.com/gardener/landscaper/pkg/components/cnudie/componentresolvers" - "github.com/gardener/landscaper/pkg/components/model/componentoverwrites" "github.com/gardener/landscaper/pkg/components/registries" "github.com/gardener/landscaper/pkg/landscaper/installations" @@ -174,7 +170,7 @@ var _ = Describe("Context", func() { extCtx, err := installations.GetExternalContext(ctx, testenv.Client, inst) Expect(err).ToNot(HaveOccurred()) Expect(inst.Spec.ComponentDescriptor.Reference.RepositoryContext.Raw).To(MatchJSON(repoCtx.Raw)) - Expect(extCtx.RepositoryContext.Raw).To(MatchJSON(repoCtx.Raw)) + Expect(extCtx.ResultingRepositoryContext.Raw).To(MatchJSON(repoCtx.Raw)) }) It("should throw an error if a component name and version is defined but no repository context", func() { @@ -242,8 +238,10 @@ var _ = Describe("Context", func() { extCtx, err := installations.GetExternalContext(ctx, testenv.Client, inst) Expect(err).ToNot(HaveOccurred()) - Expect(cdv2.UnstructuredTypesEqual(inst.Spec.ComponentDescriptor.Reference.RepositoryContext, repoCtx)).To(BeTrue()) - Expect(cdv2.UnstructuredTypesEqual(extCtx.RepositoryContext, repoCtx)).To(BeTrue()) + // the installation should remain unchanged + Expect(cdv2.UnstructuredTypesEqual(inst.Spec.ComponentDescriptor.Reference.RepositoryContext, testutils.ExampleRepositoryContext())).To(BeTrue()) + // the resulting repository context should contain the result of the overwriting + Expect(cdv2.UnstructuredTypesEqual(extCtx.ResultingRepositoryContext, repoCtx)).To(BeTrue()) }) It("should overwrite a repository context defined by the external context", func() { @@ -287,8 +285,10 @@ var _ = Describe("Context", func() { extCtx, err := installations.GetExternalContext(ctx, testenv.Client, inst) Expect(err).ToNot(HaveOccurred()) - Expect(cdv2.UnstructuredTypesEqual(inst.Spec.ComponentDescriptor.Reference.RepositoryContext, repoCtx)).To(BeTrue()) - Expect(cdv2.UnstructuredTypesEqual(extCtx.RepositoryContext, repoCtx)).To(BeTrue()) + // the installation should remain unchanged + Expect(inst.Spec.ComponentDescriptor.Reference.RepositoryContext).To(BeNil()) + // the resulting repository context should contain the result of the overwriting + Expect(cdv2.UnstructuredTypesEqual(extCtx.ResultingRepositoryContext, repoCtx)).To(BeTrue()) }) }) @@ -314,20 +314,16 @@ var _ = Describe("Context", func() { Context("InjectComponentDescriptorRef", func() { It("should inject the component ref", func() { extCtx := installations.ExternalContext{ - Context: lsv1alpha1.Context{ - ContextConfiguration: lsv1alpha1.ContextConfiguration{ - RepositoryContext: testutils.ExampleRepositoryContext(), - }, - }, - ComponentName: "example.com/a", - ComponentVersion: "0.0.1", + ResultingRepositoryContext: testutils.ExampleRepositoryContext(), + ComponentName: "example.com/a", + ComponentVersion: "0.0.1", } inst := &lsv1alpha1.Installation{} extCtx.InjectComponentDescriptorRef(inst) Expect(inst.Spec.ComponentDescriptor).ToNot(BeNil()) Expect(inst.Spec.ComponentDescriptor.Reference).To(gstruct.PointTo(gstruct.MatchAllFields(gstruct.Fields{ - "RepositoryContext": Equal(extCtx.RepositoryContext), + "RepositoryContext": Equal(extCtx.ResultingRepositoryContext), "ComponentName": Equal("example.com/a"), "Version": Equal("0.0.1"), }))) @@ -335,13 +331,9 @@ var _ = Describe("Context", func() { It("should overwrite the component ref", func() { extCtx := installations.ExternalContext{ - Context: lsv1alpha1.Context{ - ContextConfiguration: lsv1alpha1.ContextConfiguration{ - RepositoryContext: testutils.ExampleRepositoryContext(), - }, - }, - ComponentName: "example.com/a", - ComponentVersion: "0.0.1", + ResultingRepositoryContext: testutils.ExampleRepositoryContext(), + ComponentName: "example.com/a", + ComponentVersion: "0.0.1", } inst := &lsv1alpha1.Installation{} @@ -354,7 +346,7 @@ var _ = Describe("Context", func() { extCtx.InjectComponentDescriptorRef(inst) Expect(inst.Spec.ComponentDescriptor).ToNot(BeNil()) Expect(inst.Spec.ComponentDescriptor.Reference).To(gstruct.PointTo(gstruct.MatchAllFields(gstruct.Fields{ - "RepositoryContext": Equal(extCtx.RepositoryContext), + "RepositoryContext": Equal(extCtx.ResultingRepositoryContext), "ComponentName": Equal("example.com/a"), "Version": Equal("0.0.1"), }))) diff --git a/pkg/landscaper/installations/executions/operation.go b/pkg/landscaper/installations/executions/operation.go index c31cd5268c..4cfafb842f 100644 --- a/pkg/landscaper/installations/executions/operation.go +++ b/pkg/landscaper/installations/executions/operation.go @@ -71,7 +71,7 @@ func (o *ExecutionOperation) RenderDeployItemTemplates(ctx context.Context, executions, err := tmpl.TemplateDeployExecutions( template.NewDeployExecutionOptions( template.NewBlueprintExecutionOptions( - o.Context().External.InjectComponentDescriptorRef(inst.GetInstallation()), + o.Context().External.InjectComponentDescriptorRef(inst.GetInstallation().DeepCopy()), inst.GetBlueprint(), o.ComponentVersion, o.ResolvedComponentDescriptorList, diff --git a/pkg/landscaper/installations/executions/operation_test.go b/pkg/landscaper/installations/executions/operation_test.go index ea333d2370..e25fdcc4ee 100644 --- a/pkg/landscaper/installations/executions/operation_test.go +++ b/pkg/landscaper/installations/executions/operation_test.go @@ -82,13 +82,9 @@ var _ = Describe("Execution Operation", func() { Name: "default", Parent: nil, External: installations.ExternalContext{ - Context: lsv1alpha1.Context{ - ContextConfiguration: lsv1alpha1.ContextConfiguration{ - RepositoryContext: &repositoryContext, - }, - }, - ComponentName: "example.com/root", - ComponentVersion: "v1.0.0", + ResultingRepositoryContext: &repositoryContext, + ComponentName: "example.com/root", + ComponentVersion: "v1.0.0", }, } diff --git a/pkg/landscaper/installations/imports/constructor.go b/pkg/landscaper/installations/imports/constructor.go index ad54c18ba0..e9a9cb4756 100644 --- a/pkg/landscaper/installations/imports/constructor.go +++ b/pkg/landscaper/installations/imports/constructor.go @@ -354,7 +354,7 @@ func (c *Constructor) RenderImportExecutions() error { spiff.New(templateStateHandler, targetResolver)) errors, bindings, err := tmpl.TemplateImportExecutions( template.NewBlueprintExecutionOptions( - c.Operation.Context().External.InjectComponentDescriptorRef(c.Operation.Inst.GetInstallation()), + c.Operation.Context().External.InjectComponentDescriptorRef(c.Operation.Inst.GetInstallation().DeepCopy()), c.Operation.Inst.GetBlueprint(), c.Operation.ComponentVersion, c.Operation.ResolvedComponentDescriptorList, diff --git a/pkg/landscaper/installations/subinstallations/helper.go b/pkg/landscaper/installations/subinstallations/helper.go index 8187f65b4f..7f27953ffd 100644 --- a/pkg/landscaper/installations/subinstallations/helper.go +++ b/pkg/landscaper/installations/subinstallations/helper.go @@ -49,6 +49,7 @@ func GetBlueprintDefinitionFromInstallationTemplate( } // resolve component descriptor list + // TODO: why is the overwriter not relevant here? _, res, err := uri.Get(componentVersion, repositoryContext) if err != nil { return nil, nil, fmt.Errorf("unable to resolve blueprint ref in component descriptor %s: %w", componentVersion.GetName(), err) @@ -85,7 +86,16 @@ func GetBlueprintDefinitionFromInstallationTemplate( if cdDef.Inline == nil { cdDef = &lsv1alpha1.ComponentDescriptorDefinition{ - Reference: subInstCdRef, + Reference: &lsv1alpha1.ComponentDescriptorReference{ + ComponentName: subInstCdRef.ComponentName, + Version: subInstCdRef.Version, + }, + } + + // Usually, the repository context of the parent installation is specified in the context resource or ocm config. + // Only if it is specified directly in the parent installation, we specify the same repository context in the subinstallation. + if inst.Spec.ComponentDescriptor != nil && inst.Spec.ComponentDescriptor.Reference != nil { + cdDef.Reference.RepositoryContext = inst.Spec.ComponentDescriptor.Reference.RepositoryContext } } diff --git a/pkg/landscaper/installations/subinstallations/subinstallations_test.go b/pkg/landscaper/installations/subinstallations/subinstallations_test.go index dab4506ebb..27afa7f276 100644 --- a/pkg/landscaper/installations/subinstallations/subinstallations_test.go +++ b/pkg/landscaper/installations/subinstallations/subinstallations_test.go @@ -171,8 +171,9 @@ var _ = Describe("SubInstallation", func() { Expect(subinsts[0].Spec.ComponentDescriptor.Reference.ComponentName).To(Equal("example.com/root")) Expect(subinsts[0].Spec.ComponentDescriptor.Reference.Version).To(Equal("1.0.0")) - Expect(subinsts[0].Spec.ComponentDescriptor.Reference.RepositoryContext.Object["baseUrl"]).To(Equal("./testdata/registry")) - Expect(subinsts[0].Spec.ComponentDescriptor.Reference.RepositoryContext.Object["type"]).To(Equal("ociRegistry")) + // expecting the same repository context as in the root installation + Expect(subinsts[0].Spec.ComponentDescriptor.Reference.RepositoryContext.Object["baseUrl"]).To(Equal("../testdata/registry")) + Expect(subinsts[0].Spec.ComponentDescriptor.Reference.RepositoryContext.Object["type"]).To(Equal("local")) Expect(subinsts[0].Spec.Blueprint.Reference.ResourceName).To(Equal("def-1")) diff --git a/pkg/landscaper/registry/components/cdutils/uri.go b/pkg/landscaper/registry/components/cdutils/uri.go index f98f33e10b..8684bcafd2 100644 --- a/pkg/landscaper/registry/components/cdutils/uri.go +++ b/pkg/landscaper/registry/components/cdutils/uri.go @@ -132,13 +132,11 @@ func (u *URI) Get(cd model.ComponentVersion, repositoryContext *types.Unstructur func (u *URI) GetComponent(cd model.ComponentVersion, repositoryContext *types.UnstructuredTypedObject, overwriter componentoverwrites.Overwriter) (model.ComponentVersion, *lsv1alpha1.ComponentDescriptorReference, error) { - cdRepositoryContext := cd.GetRepositoryContext() - var ( ctx = context.Background() component = cd cdRef = &lsv1alpha1.ComponentDescriptorReference{ - RepositoryContext: cdRepositoryContext, + RepositoryContext: repositoryContext, ComponentName: cd.GetName(), Version: cd.GetVersion(), }