diff --git a/internal/component/component_manager.go b/internal/component/component_manager.go index cb8d0dc..85f2a18 100644 --- a/internal/component/component_manager.go +++ b/internal/component/component_manager.go @@ -9,7 +9,7 @@ import ( // ComponentManager bundles the OCM logic required by the FluxDeployer. type ComponentManager interface { - GetComponentWithImageResources(ctx context.Context, resourceName string) (*ocm_cli.ComponentVersion, error) + GetComponentsWithImageResources(ctx context.Context, resourceName string) ([]ocm_cli.ComponentVersion, error) DownloadTemplatesResource(ctx context.Context, downloadDir string) error } @@ -35,8 +35,8 @@ func NewComponentManager(ctx context.Context, config *cfg.BootstrapperConfig, oc return m, nil } -func (m *ComponentManagerImpl) GetComponentWithImageResources(ctx context.Context, resourceName string) (*ocm_cli.ComponentVersion, error) { - return m.ComponentGetter.GetComponentVersionForResourceRecursive(ctx, m.ComponentGetter.RootComponentVersion(), resourceName) +func (m *ComponentManagerImpl) GetComponentsWithImageResources(ctx context.Context, resourceName string) ([]ocm_cli.ComponentVersion, error) { + return m.ComponentGetter.GetComponentVersionsForResourceRecursive(ctx, m.ComponentGetter.RootComponentVersion(), resourceName) } func (m *ComponentManagerImpl) DownloadTemplatesResource(ctx context.Context, downloadDir string) error { diff --git a/internal/component/component_manager_mock.go b/internal/component/component_manager_mock.go index 6c226f1..b83d585 100644 --- a/internal/component/component_manager_mock.go +++ b/internal/component/component_manager_mock.go @@ -19,8 +19,12 @@ type MockComponentManager struct { var _ ComponentManager = (*MockComponentManager)(nil) -func (m MockComponentManager) GetComponentWithImageResources(_ context.Context, _ string) (*ocmcli.ComponentVersion, error) { - return loadComponentVersion(m.ComponentPath) +func (m MockComponentManager) GetComponentsWithImageResources(_ context.Context, _ string) ([]ocmcli.ComponentVersion, error) { + cv, err := loadComponentVersion(m.ComponentPath) + if err != nil { + return nil, err + } + return []ocmcli.ComponentVersion{*cv}, nil } func (m MockComponentManager) DownloadTemplatesResource(_ context.Context, downloadDir string) error { diff --git a/internal/deployment-repo/deploymentRepoManager.go b/internal/deployment-repo/deploymentRepoManager.go index 83bc973..b88ce0d 100644 --- a/internal/deployment-repo/deploymentRepoManager.go +++ b/internal/deployment-repo/deploymentRepoManager.go @@ -147,15 +147,23 @@ func (m *DeploymentRepoManager) Initialize(ctx context.Context) (*DeploymentRepo logger.Infof("Fetching openmcp-operator component version") - m.openMCPOperatorCV, err = m.compGetter.GetReferencedComponentVersionRecursive(ctx, m.compGetter.RootComponentVersion(), OpenMCPOperatorComponentName) + openMCPOperatorCVs, err := m.compGetter.GetReferencedComponentVersionsRecursive(ctx, m.compGetter.RootComponentVersion(), OpenMCPOperatorComponentName) if err != nil { return m, fmt.Errorf("failed to get openmcp-operator component version: %w", err) } + if len(openMCPOperatorCVs) != 1 { + return m, fmt.Errorf("expected exactly one openmcp-operator component version, got %d", len(openMCPOperatorCVs)) + } + m.openMCPOperatorCV = &openMCPOperatorCVs[0] - m.fluxcdCV, err = m.compGetter.GetComponentVersionForResourceRecursive(ctx, m.compGetter.RootComponentVersion(), FluxCDSourceControllerResourceName) + fluxcdCVs, err := m.compGetter.GetComponentVersionsForResourceRecursive(ctx, m.compGetter.RootComponentVersion(), FluxCDSourceControllerResourceName) if err != nil { return m, fmt.Errorf("failed to get fluxcd source controller component version: %w", err) } + if len(fluxcdCVs) != 1 { + return m, fmt.Errorf("expected exactly one fluxcd source controller component version, got %d", len(fluxcdCVs)) + } + m.fluxcdCV = &fluxcdCVs[0] m.gitConfig, err = gitconfig.ParseConfig(m.GitConfigPath) if err != nil { @@ -339,34 +347,42 @@ func (m *DeploymentRepoManager) ApplyCustomResourceDefinitions(ctx context.Conte } for _, clusterProvider := range m.Config.Providers.ClusterProviders { - clusterProviderCV, err := m.compGetter.GetReferencedComponentVersionRecursive(ctx, m.compGetter.RootComponentVersion(), "cluster-provider-"+clusterProvider.Name) + clusterProviderCVs, err := m.compGetter.GetReferencedComponentVersionsRecursive(ctx, m.compGetter.RootComponentVersion(), "cluster-provider-"+clusterProvider.Name) if err != nil { return fmt.Errorf("failed to get component version for cluster provider %s: %w", clusterProvider, err) } - - err = m.applyCRDsForComponentVersion(ctx, clusterProviderCV, crdDirectory) + if len(clusterProviderCVs) != 1 { + return fmt.Errorf("expected exactly one component version for cluster provider %s, got %d", clusterProvider, len(clusterProviderCVs)) + } + err = m.applyCRDsForComponentVersion(ctx, &clusterProviderCVs[0], crdDirectory) if err != nil { logger.Warnf("Failed to apply CRDs for cluster provider %s: %v", clusterProvider, err) } } for _, serviceProvider := range m.Config.Providers.ServiceProviders { - serviceProviderCV, err := m.compGetter.GetReferencedComponentVersionRecursive(ctx, m.compGetter.RootComponentVersion(), "service-provider-"+serviceProvider.Name) + serviceProviderCVs, err := m.compGetter.GetReferencedComponentVersionsRecursive(ctx, m.compGetter.RootComponentVersion(), "service-provider-"+serviceProvider.Name) if err != nil { return fmt.Errorf("failed to get component version for service provider %s: %w", serviceProvider, err) } - err = m.applyCRDsForComponentVersion(ctx, serviceProviderCV, crdDirectory) + if len(serviceProviderCVs) != 1 { + return fmt.Errorf("expected exactly one component version for service provider %s, got %d", serviceProvider, len(serviceProviderCVs)) + } + err = m.applyCRDsForComponentVersion(ctx, &serviceProviderCVs[0], crdDirectory) if err != nil { logger.Warnf("Failed to apply CRDs for service provider %s: %v", serviceProvider, err) } } for _, platformService := range m.Config.Providers.PlatformServices { - platformServiceCV, err := m.compGetter.GetReferencedComponentVersionRecursive(ctx, m.compGetter.RootComponentVersion(), "platform-service-"+platformService.Name) + platformServiceCVs, err := m.compGetter.GetReferencedComponentVersionsRecursive(ctx, m.compGetter.RootComponentVersion(), "platform-service-"+platformService.Name) if err != nil { return fmt.Errorf("failed to get component version for platform service %s: %w", platformService, err) } - err = m.applyCRDsForComponentVersion(ctx, platformServiceCV, crdDirectory) + if len(platformServiceCVs) != 1 { + return fmt.Errorf("expected exactly one component version for platform service %s, got %d", platformService, len(platformServiceCVs)) + } + err = m.applyCRDsForComponentVersion(ctx, &platformServiceCVs[0], crdDirectory) if err != nil { logger.Warnf("Failed to apply CRDs for platform service %s: %v", platformService, err) } diff --git a/internal/deployment-repo/templater.go b/internal/deployment-repo/templater.go index 39c7520..2735e19 100644 --- a/internal/deployment-repo/templater.go +++ b/internal/deployment-repo/templater.go @@ -153,12 +153,15 @@ func TemplateProviders(ctx context.Context, clusterProviders, serviceProviders, } for _, cp := range clusterProviders { - componentVersion, err := ocmGetter.GetReferencedComponentVersionRecursive(ctx, ocmGetter.RootComponentVersion(), "cluster-provider-"+cp.Name) + componentVersions, err := ocmGetter.GetReferencedComponentVersionsRecursive(ctx, ocmGetter.RootComponentVersion(), "cluster-provider-"+cp.Name) if err != nil { return fmt.Errorf("failed to get component version for cluster provider %s: %w", cp, err) } + if len(componentVersions) != 1 { + return fmt.Errorf("expected exactly one component version for cluster provider %s, got %d", cp, len(componentVersions)) + } - imageResource, err := getImageResource(componentVersion) + imageResource, err := getImageResource(&componentVersions[0]) if err != nil { return fmt.Errorf("failed to get image resource for cluster provider %s: %w", cp, err) } @@ -177,12 +180,15 @@ func TemplateProviders(ctx context.Context, clusterProviders, serviceProviders, } for _, sp := range serviceProviders { - componentVersion, err := ocmGetter.GetReferencedComponentVersionRecursive(ctx, ocmGetter.RootComponentVersion(), "service-provider-"+sp.Name) + componentVersions, err := ocmGetter.GetReferencedComponentVersionsRecursive(ctx, ocmGetter.RootComponentVersion(), "service-provider-"+sp.Name) if err != nil { return fmt.Errorf("failed to get component version for service provider %s: %w", sp, err) } + if len(componentVersions) != 1 { + return fmt.Errorf("expected exactly one component version for service provider %s, got %d", sp, len(componentVersions)) + } - imageResource, err := getImageResource(componentVersion) + imageResource, err := getImageResource(&componentVersions[0]) if err != nil { return fmt.Errorf("failed to get image resource for service provider %s: %w", sp, err) } @@ -201,12 +207,15 @@ func TemplateProviders(ctx context.Context, clusterProviders, serviceProviders, } for _, ps := range platformServices { - componentVersion, err := ocmGetter.GetReferencedComponentVersionRecursive(ctx, ocmGetter.RootComponentVersion(), "platform-service-"+ps.Name) + componentVersions, err := ocmGetter.GetReferencedComponentVersionsRecursive(ctx, ocmGetter.RootComponentVersion(), "platform-service-"+ps.Name) if err != nil { return fmt.Errorf("failed to get component version for platform service %s: %w", ps, err) } + if len(componentVersions) != 1 { + return fmt.Errorf("expected exactly one component version for platform service %s, got %d", ps, len(componentVersions)) + } - imageResource, err := getImageResource(componentVersion) + imageResource, err := getImageResource(&componentVersions[0]) if err != nil { return fmt.Errorf("failed to get image resource for platform service %s: %w", ps, err) } diff --git a/internal/deployment-repo/testdata/01/component-constructor.yaml b/internal/deployment-repo/testdata/01/component-constructor.yaml index cc52aa5..5c332fe 100644 --- a/internal/deployment-repo/testdata/01/component-constructor.yaml +++ b/internal/deployment-repo/testdata/01/component-constructor.yaml @@ -180,10 +180,10 @@ components: resources: - name: image-crossplane type: ociImage - version: v0.0.2 + version: v0.0.1 access: type: ociArtifact - imageReference: ghcr.io/openmcp-project/releasechannel/crossplane:v0.0.2 + imageReference: ghcr.io/openmcp-project/releasechannel/crossplane:v0.0.1 - name: github.com/openmcp-project/openmcp/releasechannel/crossplane version: v0.0.2 diff --git a/internal/deployment-repo/testdata/01/expected-repo/resources/openmcp/extra/test-configmap.yaml b/internal/deployment-repo/testdata/01/expected-repo/resources/openmcp/extra/test-configmap.yaml index 3695150..af1be26 100644 --- a/internal/deployment-repo/testdata/01/expected-repo/resources/openmcp/extra/test-configmap.yaml +++ b/internal/deployment-repo/testdata/01/expected-repo/resources/openmcp/extra/test-configmap.yaml @@ -13,12 +13,13 @@ data: key: "value" repository: "{{OCM_REPO_URL}}" rootComponent: "github.com/openmcp-project/openmcp" - crossplaneComponentName: "github.com/openmcp-project/openmcp/releasechannel/crossplane" - crossplaneComponentVersion: "v0.0.1" - crossplaneImage: "ghcr.io/openmcp-project/releasechannel/crossplane" - crossplaneVersions: | - - v0.0.1 - - v0.0.2 + crossplane: | + - crossplaneComponentName: "github.com/openmcp-project/openmcp/releasechannel/crossplane" + crossplaneComponentVersion: "v0.0.1" + crossplaneImage: "ghcr.io/openmcp-project/releasechannel/crossplane:v0.0.1" + - crossplaneComponentName: "github.com/openmcp-project/openmcp/releasechannel/crossplane" + crossplaneComponentVersion: "v0.0.2" + crossplaneImage: "ghcr.io/openmcp-project/releasechannel/crossplane:v0.0.2" platformService: | image: "ghcr.io/openmcp-project/images/platform-service-test" version: "v0.3.0" \ No newline at end of file diff --git a/internal/deployment-repo/testdata/01/extra-manifests/test-configmap.yaml b/internal/deployment-repo/testdata/01/extra-manifests/test-configmap.yaml index 93d7f43..d7f317c 100644 --- a/internal/deployment-repo/testdata/01/extra-manifests/test-configmap.yaml +++ b/internal/deployment-repo/testdata/01/extra-manifests/test-configmap.yaml @@ -9,20 +9,22 @@ data: key: "value" repository: "{{ getOCMRepository }}" rootComponent: "{{ dig "component" "name" "none" (componentVersionAsMap (getRootComponentVersion)) }}" - {{- $releaseChannelCv := getComponentVersionByReference "releasechannel" }} - {{- $crossplaneCv := getComponentVersionByReference $releaseChannelCv "crossplane" }} - {{- $crossplaneImageResource := getResourceFromComponentVersion $crossplaneCv "image-crossplane" }} - {{- $imageReference := dig "access" "imageReference" "none" $crossplaneImageResource }} - {{- $parsedImage := parseImage $imageReference }} - {{- $crossplaneCvMap := componentVersionAsMap $crossplaneCv }} - crossplaneComponentName: "{{ dig "component" "name" "none" $crossplaneCvMap }}" - crossplaneComponentVersion: "{{ dig "component" "version" "none" $crossplaneCvMap }}" - crossplaneImage: "{{ dig "image" "none" $parsedImage }}" - crossplaneVersions: | - {{- $crossplaneVersions := listComponentVersions $crossplaneCv }} -{{ toYaml (sortAlpha $crossplaneVersions) | indent 4 }} + {{- $releaseChannelCvs := getComponentVersionsByReference "releasechannel" }} + {{- $releaseChannelCv := index $releaseChannelCvs 0 }} + {{- $crossplaneCvs := getComponentVersionsByReference $releaseChannelCv "crossplane" }} + crossplane: | + {{- range $crossplaneCv := $crossplaneCvs }} + {{- $crossplaneImageResource := getResourceFromComponentVersion $crossplaneCv "image-crossplane" }} + {{- $imageReference := dig "access" "imageReference" "none" $crossplaneImageResource }} + {{- $parsedImage := parseImage $imageReference }} + {{- $crossplaneCvMap := componentVersionAsMap $crossplaneCv }} + - crossplaneComponentName: "{{ dig "component" "name" "none" $crossplaneCvMap }}" + crossplaneComponentVersion: "{{ dig "component" "version" "none" $crossplaneCvMap }}" + crossplaneImage: "{{ dig "image" "none" $parsedImage }}:{{ dig "tag" "none" $parsedImage }}" + {{- end }} platformService: | - {{- $platformServiceCv := getComponentVersionForResource "platform-service-test-image" }} + {{- $platformServiceCvs := getComponentVersionsForResource "platform-service-test-image" }} + {{- $platformServiceCv := index $platformServiceCvs 0 }} {{- $platformServiceImageResource := getResourceFromComponentVersion $platformServiceCv "platform-service-test-image" }} {{- $platformServiceImageReference := dig "access" "imageReference" "none" $platformServiceImageResource }} {{- $platformServiceParsedImage := parseImage $platformServiceImageReference }} diff --git a/internal/eso-deployer/deployer.go b/internal/eso-deployer/deployer.go index 8e8eb21..d555bc2 100644 --- a/internal/eso-deployer/deployer.go +++ b/internal/eso-deployer/deployer.go @@ -50,10 +50,14 @@ func (d *EsoDeployer) Deploy(ctx context.Context) error { func (d *EsoDeployer) DeployWithComponentManager(ctx context.Context, componentManager component.ComponentManager) error { d.log.Info("Getting OCM component containing ESO resources.") - esoComponent, err := componentManager.GetComponentWithImageResources(ctx, "external-secrets-operator-image") + esoComponents, err := componentManager.GetComponentsWithImageResources(ctx, "external-secrets-operator-image") if err != nil { return fmt.Errorf("failed to get external-secrets-operator-image component: %w", err) } + if len(esoComponents) != 1 { + return fmt.Errorf("expected exactly one component with external-secrets-operator-image resource, got %d", len(esoComponents)) + } + esoComponent := &esoComponents[0] esoChartRes, err := esoComponent.GetResource("external-secrets-operator-chart") if err != nil { diff --git a/internal/flux_deployer/deployer.go b/internal/flux_deployer/deployer.go index cfaebff..91c15f8 100644 --- a/internal/flux_deployer/deployer.go +++ b/internal/flux_deployer/deployer.go @@ -109,10 +109,14 @@ func (d *FluxDeployer) DeployWithComponentManager(ctx context.Context, component d.log.Tracef("Created repo directory: %s", d.repoDir) // Get component which contains the fluxcd images as resources - d.fluxcdCV, err = componentManager.GetComponentWithImageResources(ctx, FluxCDSourceControllerResourceName) + fluxcdCVs, err := componentManager.GetComponentsWithImageResources(ctx, FluxCDSourceControllerResourceName) if err != nil { return fmt.Errorf("failed to get fluxcd source controller component version: %w", err) } + if len(fluxcdCVs) != 1 { + return fmt.Errorf("expected exactly one fluxcd component version with resource %s, got %d", FluxCDSourceControllerResourceName, len(fluxcdCVs)) + } + d.fluxcdCV = &fluxcdCVs[0] // Download resource from gitops-templates component into the download directory d.log.Info("Downloading templates") diff --git a/internal/ocm-cli/component_getter.go b/internal/ocm-cli/component_getter.go index 0a5c0b3..0e9df20 100644 --- a/internal/ocm-cli/component_getter.go +++ b/internal/ocm-cli/component_getter.go @@ -56,10 +56,14 @@ func (g *ComponentGetter) InitializeComponents(ctx context.Context) error { cv := g.rootComponentVersion for _, refName := range referenceNames { - cv, err = g.GetReferencedComponentVersionRecursive(ctx, cv, refName) + cvs, err := g.GetReferencedComponentVersionsRecursive(ctx, cv, refName) if err != nil { return fmt.Errorf("error getting referenced component version %s: %w", refName, err) } + if len(cvs) != 1 { + return fmt.Errorf("expected exactly one component version for reference %s, got %d", refName, len(cvs)) + } + cv = &cvs[0] } g.templatesComponentVersion = cv @@ -87,69 +91,74 @@ func (g *ComponentGetter) OCMConfig() string { return g.ocmConfig } -func (g *ComponentGetter) GetReferencedComponentVersion(ctx context.Context, parentCV *ComponentVersion, refName string) (*ComponentVersion, error) { +func (g *ComponentGetter) GetReferencedComponentVersions(ctx context.Context, parentCV *ComponentVersion, refName string) ([]ComponentVersion, error) { logger := log.GetLogger() logger.Tracef("Comp_Getter: Getting component reference %s in component version %s", refName, parentCV.Component.Name) - ref, err := parentCV.GetComponentReference(refName) - if err != nil { - return nil, fmt.Errorf("error getting component reference %s: %w", refName, err) - } + refs := parentCV.GetComponentReferences(refName) + componentVersions := make([]ComponentVersion, 0, len(refs)) - location := buildLocation(g.repo, ref.ComponentName, ref.Version) - cv, err := GetComponentVersion(ctx, location, g.ocmConfig) - if err != nil { - return nil, fmt.Errorf("error getting component version %s: %w", location, err) + for _, ref := range refs { + location := buildLocation(g.repo, ref.ComponentName, ref.Version) + cv, err := GetComponentVersion(ctx, location, g.ocmConfig) + if err != nil { + return nil, fmt.Errorf("error getting component version %s: %w", location, err) + } + componentVersions = append(componentVersions, *cv) } logger.Tracef("Comp_Getter: Found component reference %s in component version %s", refName, parentCV.Component.Name) - return cv, nil + return componentVersions, nil } -func (g *ComponentGetter) GetReferencedComponentVersionRecursive(ctx context.Context, parentCV *ComponentVersion, refName string) (*ComponentVersion, error) { +func (g *ComponentGetter) GetReferencedComponentVersionsRecursive(ctx context.Context, parentCV *ComponentVersion, refName string) ([]ComponentVersion, error) { logger := log.GetLogger() logger.Tracef("Comp_Getter: Searching for component reference %s in component version %s", refName, parentCV.Component.Name) // First, try to get the reference directly from the parent component version - ref, err := g.GetReferencedComponentVersion(ctx, parentCV, refName) + refs, err := g.GetReferencedComponentVersions(ctx, parentCV, refName) if err == nil { - return ref, nil + return refs, nil } // If not found, search recursively in all component references for _, componentRef := range parentCV.Component.ComponentReferences { - subCV, err := g.GetReferencedComponentVersion(ctx, parentCV, componentRef.Name) + subCVs, err := g.GetReferencedComponentVersions(ctx, parentCV, componentRef.Name) if err != nil { continue } - ref, err := g.GetReferencedComponentVersionRecursive(ctx, subCV, refName) - if err == nil { - return ref, nil + for _, subCV := range subCVs { + subCvRefs, err := g.GetReferencedComponentVersionsRecursive(ctx, &subCV, refName) + if err == nil { + return subCvRefs, nil + } } } return nil, fmt.Errorf("component reference %s not found in component version %s or its references", refName, parentCV.Component.Name) } -func (g *ComponentGetter) GetComponentVersionForResourceRecursive(ctx context.Context, parentCV *ComponentVersion, resourceName string) (*ComponentVersion, error) { +func (g *ComponentGetter) GetComponentVersionsForResourceRecursive(ctx context.Context, parentCV *ComponentVersion, resourceName string) ([]ComponentVersion, error) { logger := log.GetLogger() logger.Tracef("Comp_Getter: Searching for resource %s in component version %s", resourceName, parentCV.Component.Name) // Check if the resource exists in the current component version _, err := parentCV.GetResource(resourceName) if err == nil { - return parentCV, nil + return []ComponentVersion{*parentCV}, nil } // If not found, search recursively in all component references for _, componentRef := range parentCV.Component.ComponentReferences { - subCV, err := g.GetReferencedComponentVersion(ctx, parentCV, componentRef.Name) + subCVs, err := g.GetReferencedComponentVersions(ctx, parentCV, componentRef.Name) if err != nil { continue } - cv, err := g.GetComponentVersionForResourceRecursive(ctx, subCV, resourceName) - if err == nil { - return cv, nil + for _, subCV := range subCVs { + cvs, err := g.GetComponentVersionsForResourceRecursive(ctx, &subCV, resourceName) + if err == nil { + return cvs, nil + } } } @@ -164,8 +173,6 @@ func (g *ComponentGetter) DownloadDirectoryResourceByLocation(ctx context.Contex logger := log.GetLogger() logger.Tracef("Comp_Getter: Downloading directory resource from location %s", location) - var err error - location = strings.TrimSpace(location) segments := strings.Split(location, "/") if len(segments) == 0 { @@ -177,10 +184,11 @@ func (g *ComponentGetter) DownloadDirectoryResourceByLocation(ctx context.Contex cv := rootCV for _, refName := range referenceNames { - cv, err = g.GetReferencedComponentVersionRecursive(ctx, cv, refName) + cvs, err := g.GetReferencedComponentVersionsRecursive(ctx, cv, refName) if err != nil { return fmt.Errorf("error getting referenced component version %s: %w", refName, err) } + cv = &cvs[0] } componentLocation := buildLocation(g.repo, cv.Component.Name, cv.Component.Version) diff --git a/internal/ocm-cli/ocm.go b/internal/ocm-cli/ocm.go index a010fee..7d3bf2c 100644 --- a/internal/ocm-cli/ocm.go +++ b/internal/ocm-cli/ocm.go @@ -164,14 +164,16 @@ func (cv *ComponentVersion) GetResourcesByType(resourceType string) []Resource { return resources } -// GetComponentReference retrieves a component reference by its name from the component version. -func (cv *ComponentVersion) GetComponentReference(name string) (*ComponentReference, error) { +// GetComponentReferences retrieves component references by its name from the component version. +func (cv *ComponentVersion) GetComponentReferences(name string) []ComponentReference { + references := make([]ComponentReference, 0) + for _, ref := range cv.Component.ComponentReferences { if ref.Name == name { - return &ref, nil + references = append(references, ref) } } - return nil, fmt.Errorf("component reference %s not found in component version %s", name, cv.Component.Name) + return references } func (cv *ComponentVersion) ListComponentVersions(ctx context.Context, ocmConfig string) ([]string, error) { diff --git a/internal/template/template.go b/internal/template/template.go index 80f0c10..13c9627 100644 --- a/internal/template/template.go +++ b/internal/template/template.go @@ -38,7 +38,7 @@ func getRootComponentVersion(compGetter *ocmcli.ComponentGetter) *ocmcli.Compone return compGetter.RootComponentVersion() } -func getComponentVersionByReference(ctx context.Context, compGetter *ocmcli.ComponentGetter, args ...interface{}) *ocmcli.ComponentVersion { +func getComponentVersionsByReference(ctx context.Context, compGetter *ocmcli.ComponentGetter, args ...interface{}) []ocmcli.ComponentVersion { logger := log.GetLogger() if compGetter == nil { @@ -50,27 +50,27 @@ func getComponentVersionByReference(ctx context.Context, compGetter *ocmcli.Comp } var err error - parentCv := compGetter.RootComponentVersion() + parentCv := *compGetter.RootComponentVersion() referenceName := args[len(args)-1].(string) if len(args) == 2 { - parentCv = args[0].(*ocmcli.ComponentVersion) + parentCv = args[0].(ocmcli.ComponentVersion) } logger.Tracef("Template_Func: getComponentVersionByReference called with parent component version: %s and reference name: %s", parentCv.Component.Name, referenceName) - cv, err := compGetter.GetReferencedComponentVersionRecursive(ctx, parentCv, referenceName) - if err != nil || cv == nil { + cvs, err := compGetter.GetReferencedComponentVersionsRecursive(ctx, &parentCv, referenceName) + if err != nil || cvs == nil { if err != nil { logger.Errorf("Template_Func: getComponentVersionByReference error getting component version by reference %s from parent component version %s: %v", referenceName, parentCv.Component.Name, err) } return nil } - return cv + return cvs } -func getComponentVersionForResource(ctx context.Context, compGetter *ocmcli.ComponentGetter, args ...interface{}) *ocmcli.ComponentVersion { +func getComponentVersionsForResource(ctx context.Context, compGetter *ocmcli.ComponentGetter, args ...interface{}) []ocmcli.ComponentVersion { logger := log.GetLogger() if compGetter == nil { @@ -82,30 +82,26 @@ func getComponentVersionForResource(ctx context.Context, compGetter *ocmcli.Comp } var err error - parentCv := compGetter.RootComponentVersion() + parentCv := *compGetter.RootComponentVersion() referenceName := args[len(args)-1].(string) if len(args) == 2 { - parentCv = args[0].(*ocmcli.ComponentVersion) + parentCv = args[0].(ocmcli.ComponentVersion) } logger.Tracef("Template_Func: getComponentVersionForResource called with parent component version: %s and reference name: %s", parentCv.Component.Name, referenceName) - cv, err := compGetter.GetComponentVersionForResourceRecursive(ctx, parentCv, referenceName) - if err != nil || cv == nil { + cvs, err := compGetter.GetComponentVersionsForResourceRecursive(ctx, &parentCv, referenceName) + if err != nil || cvs == nil { if err != nil { logger.Errorf("Template_Func: getComponentVersionForResource error getting component version for resource %s from parent component version %s: %v", referenceName, parentCv.Component.Name, err) } return nil } - return cv + return cvs } -func componentVersionAsMap(cv *ocmcli.ComponentVersion) map[string]interface{} { - if cv == nil { - return nil - } - +func componentVersionAsMap(cv ocmcli.ComponentVersion) map[string]interface{} { m, err := yaml.Marshal(cv) if err != nil { return nil @@ -120,7 +116,7 @@ func componentVersionAsMap(cv *ocmcli.ComponentVersion) map[string]interface{} { return output } -func getResourceFromComponentVersion(compGetter *ocmcli.ComponentGetter, cv *ocmcli.ComponentVersion, resourceName string) map[string]interface{} { +func getResourceFromComponentVersion(compGetter *ocmcli.ComponentGetter, cv ocmcli.ComponentVersion, resourceName string) map[string]interface{} { logger := log.GetLogger() logger.Tracef("Template_Func: getResourceFromComponentVersion called with component version: %s and resource name: %s", cv.Component.Name, resourceName) @@ -158,7 +154,7 @@ func getOCMRepository(compGetter *ocmcli.ComponentGetter) string { return compGetter.Repository() } -func listComponentVersions(ctx context.Context, compGetter *ocmcli.ComponentGetter, cv *ocmcli.ComponentVersion) []string { +func listComponentVersions(ctx context.Context, compGetter *ocmcli.ComponentGetter, cv ocmcli.ComponentVersion) []string { logger := log.GetLogger() logger.Tracef("Template_Func: listComponentVersions called with component version: %s", cv.Component.Name) @@ -255,29 +251,29 @@ func (t *TemplateExecution) WithOCMComponentGetter(ctx context.Context, compGett "getRootComponentVersion": func() *ocmcli.ComponentVersion { return getRootComponentVersion(compGetter) }, - // getComponentVersionByReference returns a ComponentVersion based on the provided reference name. + // getComponentVersionsByReference returns a list of ComponentVersion based on the provided reference name. // It can take either one or two arguments: // - One argument: the reference name (string). The search starts from the root component version. // - Two arguments: the first argument is a ComponentVersion to start the search from, and the second argument is the reference name (string). // If the ComponentVersion is not found, it returns nil. // If the ComponentGetter is nil, it panics. // If the number of arguments is less than 1, it panics. - "getComponentVersionByReference": func(args ...interface{}) *ocmcli.ComponentVersion { - return getComponentVersionByReference(ctx, compGetter, args...) + "getComponentVersionsByReference": func(args ...interface{}) []ocmcli.ComponentVersion { + return getComponentVersionsByReference(ctx, compGetter, args...) }, - // getComponentVersionForResource returns a ComponentVersion that contains the specified resource. + // getComponentVersionsForResource returns a list of ComponentVersion that contains the specified resource. // It can take either one or two arguments: // - One argument: the resource name (string). The search starts from the root component version. // - Two arguments: the first argument is a ComponentVersion to start the search from, and the second argument is the resource name (string). // If the ComponentVersion is not found, it returns nil. // If the ComponentGetter is nil, it panics. // If the number of arguments is less than 1, it panics. - "getComponentVersionForResource": func(args ...interface{}) *ocmcli.ComponentVersion { - return getComponentVersionForResource(ctx, compGetter, args...) + "getComponentVersionsForResource": func(args ...interface{}) []ocmcli.ComponentVersion { + return getComponentVersionsForResource(ctx, compGetter, args...) }, // componentVersionAsMap converts a ComponentVersion to a map[string]interface{}. // If the ComponentVersion is nil, it returns nil. - "componentVersionAsMap": func(cv *ocmcli.ComponentVersion) map[string]interface{} { + "componentVersionAsMap": func(cv ocmcli.ComponentVersion) map[string]interface{} { return componentVersionAsMap(cv) }, // getResourceFromComponentVersion retrieves a resource from the given ComponentVersion by its name. @@ -287,7 +283,7 @@ func (t *TemplateExecution) WithOCMComponentGetter(ctx context.Context, compGett // It returns the resource as a map[string]interface{} or nil if not found. // If the ComponentGetter is nil, it panics. // If the resource is not found or an error occurs, it returns nil. - "getResourceFromComponentVersion": func(cv *ocmcli.ComponentVersion, resourceName string) map[string]interface{} { + "getResourceFromComponentVersion": func(cv ocmcli.ComponentVersion, resourceName string) map[string]interface{} { return getResourceFromComponentVersion(compGetter, cv, resourceName) }, // listComponentVersions lists all available versions of the given ComponentVersion's component. @@ -296,7 +292,7 @@ func (t *TemplateExecution) WithOCMComponentGetter(ctx context.Context, compGett // It returns a slice of version strings or nil if an error occurs. // If the ComponentGetter is nil, it panics. // If an error occurs while listing versions, it returns nil. - "listComponentVersions": func(cv *ocmcli.ComponentVersion) []string { + "listComponentVersions": func(cv ocmcli.ComponentVersion) []string { return listComponentVersions(ctx, compGetter, cv) }, })