diff --git a/cmd/main.go b/cmd/main.go index 77066580a2..9d8abeda0f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -80,11 +80,10 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/service/skrclient" skrclientcache "github.com/kyma-project/lifecycle-manager/internal/service/skrclient/cache" "github.com/kyma-project/lifecycle-manager/internal/setup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/log" "github.com/kyma-project/lifecycle-manager/pkg/matcher" "github.com/kyma-project/lifecycle-manager/pkg/queue" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" "github.com/kyma-project/lifecycle-manager/pkg/watcher" _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -383,17 +382,9 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe options.CacheSyncTimeout = flagVar.CacheSyncTimeout options.MaxConcurrentReconciles = flagVar.MaxConcurrentKymaReconciles - moduleTemplateInfoLookupStrategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(mgr.GetClient()), - moduletemplateinfolookup.NewByChannelStrategy(mgr.GetClient()), - moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(mgr.GetClient())), - }, - ) - kcpClient := mgr.GetClient() moduleStatusGen := generator.NewModuleStatusGenerator(fromerror.GenerateModuleStatusFromError) + modulesStatusHandler := modules.NewStatusHandler(moduleStatusGen, kcpClient, kymaMetrics.RemoveModuleStateMetrics) if err := (&kyma.Reconciler{ @@ -415,8 +406,7 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe Metrics: kymaMetrics, RemoteCatalog: remote.NewRemoteCatalogFromKyma(kcpClient, skrContextFactory, flagVar.RemoteSyncNamespace), - TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, - moduleTemplateInfoLookupStrategies), + TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, maintenanceWindow), }).SetupWithManager( mgr, options, kyma.SetupOptions{ ListenerAddr: flagVar.KymaListenerAddr, diff --git a/internal/controller/kyma/controller.go b/internal/controller/kyma/controller.go index 243f4aa4e7..d55ffbb908 100644 --- a/internal/controller/kyma/controller.go +++ b/internal/controller/kyma/controller.go @@ -38,12 +38,12 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" "github.com/kyma-project/lifecycle-manager/internal/remote" "github.com/kyma-project/lifecycle-manager/internal/service/accessmanager" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/log" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" "github.com/kyma-project/lifecycle-manager/pkg/module/sync" "github.com/kyma-project/lifecycle-manager/pkg/queue" "github.com/kyma-project/lifecycle-manager/pkg/status" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/util" "github.com/kyma-project/lifecycle-manager/pkg/watcher" ) diff --git a/internal/controller/mandatorymodule/installation_controller.go b/internal/controller/mandatorymodule/installation_controller.go index 82b9ec42ac..cd43c4c1e9 100644 --- a/internal/controller/mandatorymodule/installation_controller.go +++ b/internal/controller/mandatorymodule/installation_controller.go @@ -28,11 +28,11 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" "github.com/kyma-project/lifecycle-manager/internal/manifest/parser" "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/log" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" "github.com/kyma-project/lifecycle-manager/pkg/module/sync" "github.com/kyma-project/lifecycle-manager/pkg/queue" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/util" ) diff --git a/internal/manifest/parser/template_to_module.go b/internal/manifest/parser/template_to_module.go index f11158a711..a6ccb0606c 100644 --- a/internal/manifest/parser/template_to_module.go +++ b/internal/manifest/parser/template_to_module.go @@ -15,8 +15,8 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" "github.com/kyma-project/lifecycle-manager/internal/descriptor/types" "github.com/kyma-project/lifecycle-manager/internal/manifest/img" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" ) var ErrConvertingToOCIAccessSpec = errors.New("failed converting resource.AccessSpec to *ociartifact.AccessSpec") diff --git a/internal/service/kyma/status/modules/generator/fromerror/generator.go b/internal/service/kyma/status/modules/generator/fromerror/generator.go index efdf858a85..f8ca708fba 100644 --- a/internal/service/kyma/status/modules/generator/fromerror/generator.go +++ b/internal/service/kyma/status/modules/generator/fromerror/generator.go @@ -5,9 +5,8 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup/common" ) var errFunctionCalledWitNilError = errors.New("can not generate a modulestatus without error") @@ -54,11 +53,11 @@ func GenerateModuleStatusFromError(err error, moduleName, desiredChannel, fqdn s } func errorIsWaitingForMaintenanceWindow(err error) bool { - return errors.Is(err, moduletemplateinfolookup.ErrWaitingForNextMaintenanceWindow) + return errors.Is(err, templatelookup.ErrWaitingForNextMaintenanceWindow) } func errorIsMaintenanceWindowUnknown(err error) bool { - return errors.Is(err, moduletemplateinfolookup.ErrFailedToDetermineIfMaintenanceWindowIsActive) + return errors.Is(err, templatelookup.ErrFailedToDetermineIfMaintenanceWindowIsActive) } func errorIsForbiddenTemplateUpdate(err error) bool { diff --git a/internal/service/kyma/status/modules/generator/fromerror/generator_test.go b/internal/service/kyma/status/modules/generator/fromerror/generator_test.go index f92ef52d6e..89c8b68031 100644 --- a/internal/service/kyma/status/modules/generator/fromerror/generator_test.go +++ b/internal/service/kyma/status/modules/generator/fromerror/generator_test.go @@ -11,9 +11,8 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator/fromerror" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup/common" ) func TestGenerateModuleStatusFromError_WhenCalledWithAnyOtherError_ReturnsDefaultNewStatusWithStateError(t *testing.T) { @@ -50,7 +49,7 @@ func TestGenerateModuleStatusFromError_WhenCalledWithMaintenanceWindowActiveErro someChannel := "some-channel" someFQDN := "some-fqdn" status := createStatus() - templateError := moduletemplateinfolookup.ErrWaitingForNextMaintenanceWindow + templateError := templatelookup.ErrWaitingForNextMaintenanceWindow result, err := fromerror.GenerateModuleStatusFromError(templateError, someModuleName, someChannel, someFQDN, status) @@ -75,7 +74,7 @@ func TestGenerateModuleStatusFromError_WhenCalledWithMaintenanceWindowUnknownErr someChannel := "some-channel" someFQDN := "some-fqdn" status := createStatus() - templateError := moduletemplateinfolookup.ErrFailedToDetermineIfMaintenanceWindowIsActive + templateError := templatelookup.ErrFailedToDetermineIfMaintenanceWindowIsActive result, err := fromerror.GenerateModuleStatusFromError(templateError, someModuleName, someChannel, someFQDN, status) diff --git a/internal/service/kyma/status/modules/generator/generator_test.go b/internal/service/kyma/status/modules/generator/generator_test.go index 0f24795a78..3905e660bd 100644 --- a/internal/service/kyma/status/modules/generator/generator_test.go +++ b/internal/service/kyma/status/modules/generator/generator_test.go @@ -11,8 +11,8 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" ) diff --git a/pkg/templatelookup/common/errors.go b/internal/templatelookup/common/errors.go similarity index 100% rename from pkg/templatelookup/common/errors.go rename to internal/templatelookup/common/errors.go diff --git a/pkg/templatelookup/mandatory.go b/internal/templatelookup/mandatory.go similarity index 100% rename from pkg/templatelookup/mandatory.go rename to internal/templatelookup/mandatory.go diff --git a/pkg/templatelookup/mandatory_test.go b/internal/templatelookup/mandatory_test.go similarity index 99% rename from pkg/templatelookup/mandatory_test.go rename to internal/templatelookup/mandatory_test.go index 7c8f8aad40..153bdf184c 100644 --- a/pkg/templatelookup/mandatory_test.go +++ b/internal/templatelookup/mandatory_test.go @@ -8,7 +8,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" ) diff --git a/pkg/templatelookup/moduleinfo.go b/internal/templatelookup/moduleinfo.go similarity index 100% rename from pkg/templatelookup/moduleinfo.go rename to internal/templatelookup/moduleinfo.go diff --git a/pkg/templatelookup/moduleinfo_test.go b/internal/templatelookup/moduleinfo_test.go similarity index 99% rename from pkg/templatelookup/moduleinfo_test.go rename to internal/templatelookup/moduleinfo_test.go index fd0492eec9..f1422eba4f 100644 --- a/pkg/templatelookup/moduleinfo_test.go +++ b/internal/templatelookup/moduleinfo_test.go @@ -8,7 +8,7 @@ import ( apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" ) func Test_FetchModuleInfo_When_EmptySpecAndStatus(t *testing.T) { diff --git a/pkg/templatelookup/modulereleasemeta.go b/internal/templatelookup/modulereleasemeta.go similarity index 100% rename from pkg/templatelookup/modulereleasemeta.go rename to internal/templatelookup/modulereleasemeta.go diff --git a/pkg/templatelookup/modulereleasemeta_test.go b/internal/templatelookup/modulereleasemeta_test.go similarity index 96% rename from pkg/templatelookup/modulereleasemeta_test.go rename to internal/templatelookup/modulereleasemeta_test.go index c7ef291721..115ab24cf1 100644 --- a/pkg/templatelookup/modulereleasemeta_test.go +++ b/internal/templatelookup/modulereleasemeta_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" ) func Test_GetChannelVersionForModule_WhenEmptyChannels(t *testing.T) { diff --git a/pkg/templatelookup/regular.go b/internal/templatelookup/regular.go similarity index 53% rename from pkg/templatelookup/regular.go rename to internal/templatelookup/regular.go index 7f7b7f9344..bd0603faab 100644 --- a/pkg/templatelookup/regular.go +++ b/internal/templatelookup/regular.go @@ -11,14 +11,24 @@ import ( "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup/common" ) var ( - ErrTemplateNotAllowed = errors.New("module template not allowed") - ErrTemplateUpdateNotAllowed = errors.New("module template update not allowed") + ErrTemplateNotAllowed = errors.New("module template not allowed") + ErrTemplateUpdateNotAllowed = errors.New("module template update not allowed") + ErrWaitingForNextMaintenanceWindow = errors.New( + "waiting for next maintenance window to update module version", + ) + ErrFailedToDetermineIfMaintenanceWindowIsActive = errors.New("failed to determine if maintenance window is active") + ErrModuleReleaseMetaNotFound = errors.New("ModuleReleaseMeta not found for module") ) +type MaintenanceWindow interface { + IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool + IsActive(kyma *v1beta2.Kyma) (bool, error) +} + type ModuleTemplateInfo struct { *v1beta2.ModuleTemplate @@ -26,34 +36,99 @@ type ModuleTemplateInfo struct { DesiredChannel string } -type ModuleTemplateInfoLookupStrategy interface { - Lookup(ctx context.Context, - moduleInfo *ModuleInfo, - kyma *v1beta2.Kyma, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, - ) ModuleTemplateInfo -} - type TemplateLookup struct { client.Reader - descriptorProvider *provider.CachedDescriptorProvider - moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy + descriptorProvider *provider.CachedDescriptorProvider + maintenanceWindow MaintenanceWindow } func NewTemplateLookup(reader client.Reader, descriptorProvider *provider.CachedDescriptorProvider, - moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy, + maintenanceWindow MaintenanceWindow, ) *TemplateLookup { return &TemplateLookup{ - Reader: reader, - descriptorProvider: descriptorProvider, - moduleTemplateInfoLookupStrategy: moduleTemplateInfoLookupStrategy, + Reader: reader, + descriptorProvider: descriptorProvider, + maintenanceWindow: maintenanceWindow, } } type ModuleTemplatesByModuleName map[string]*ModuleTemplateInfo +// LookupModuleTemplate looks up the module template via the module release meta. +// In production, moduleReleaseMeta is guaranteed to exist for valid modules. +func LookupModuleTemplate(ctx context.Context, + clnt client.Reader, + moduleInfo *ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, +) ModuleTemplateInfo { + moduleTemplateInfo := ModuleTemplateInfo{} + moduleTemplateInfo.DesiredChannel = getDesiredChannel(moduleInfo.Channel, kyma.Spec.Channel) + + var desiredModuleVersion string + var err error + if moduleReleaseMeta.Spec.Mandatory != nil { + desiredModuleVersion, err = GetMandatoryVersionForModule(moduleReleaseMeta) + } else { + desiredModuleVersion, err = GetChannelVersionForModule(moduleReleaseMeta, + moduleTemplateInfo.DesiredChannel) + } + if err != nil { + moduleTemplateInfo.Err = err + return moduleTemplateInfo + } + + template, err := getTemplateByVersion(ctx, + clnt, + moduleInfo.Name, + desiredModuleVersion, + kyma.Namespace) + if err != nil { + moduleTemplateInfo.Err = err + return moduleTemplateInfo + } + + moduleTemplateInfo.ModuleTemplate = template + return moduleTemplateInfo +} + +// getDesiredChannel determines the desired channel based on module-specific channel or global channel. +func getDesiredChannel(moduleChannel, globalChannel string) string { + var desiredChannel string + + switch { + case moduleChannel != "": + desiredChannel = moduleChannel + case globalChannel != "": + desiredChannel = globalChannel + default: + desiredChannel = v1beta2.DefaultChannel + } + + return desiredChannel +} + +func getTemplateByVersion(ctx context.Context, + clnt client.Reader, + moduleName, + moduleVersion, + namespace string, +) (*v1beta2.ModuleTemplate, error) { + moduleTemplate := &v1beta2.ModuleTemplate{} + + moduleTemplateName := fmt.Sprintf("%s-%s", moduleName, moduleVersion) + if err := clnt.Get(ctx, client.ObjectKey{ + Name: moduleTemplateName, + Namespace: namespace, + }, moduleTemplate); err != nil { + return nil, fmt.Errorf("failed to get module template: %w", err) + } + + return moduleTemplate, nil +} + func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2.Kyma) ModuleTemplatesByModuleName { templates := make(ModuleTemplatesByModuleName) for _, moduleInfo := range FetchModuleInfo(kyma) { @@ -72,7 +147,15 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2. continue } - templateInfo := t.moduleTemplateInfoLookupStrategy.Lookup(ctx, + // If ModuleReleaseMeta doesn't exist, we can't proceed with template lookup + if moduleReleaseMeta == nil { + templates[moduleInfo.Name] = &ModuleTemplateInfo{ + Err: fmt.Errorf("%w: %s", ErrModuleReleaseMetaNotFound, moduleInfo.Name), + } + continue + } + + templateInfo := t.lookupModuleTemplateWithMaintenanceWindow(ctx, &moduleInfo, kyma, moduleReleaseMeta) @@ -104,6 +187,42 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2. return templates } +// lookupModuleTemplateWithMaintenanceWindow performs the core lookup and applies maintenance window logic. +func (t *TemplateLookup) lookupModuleTemplateWithMaintenanceWindow(ctx context.Context, + moduleInfo *ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, +) ModuleTemplateInfo { + // First perform the standard lookup + moduleTemplateInfo := LookupModuleTemplate(ctx, t.Reader, moduleInfo, kyma, moduleReleaseMeta) + + // If lookup failed or no maintenance window configured, return as-is + if moduleTemplateInfo.ModuleTemplate == nil || moduleTemplateInfo.Err != nil || t.maintenanceWindow == nil { + return moduleTemplateInfo + } + + // Check if maintenance window is required for this module template + if !t.maintenanceWindow.IsRequired(moduleTemplateInfo.ModuleTemplate, kyma) { + return moduleTemplateInfo + } + + // Check if maintenance window is currently active + active, err := t.maintenanceWindow.IsActive(kyma) + if err != nil { + moduleTemplateInfo.Err = fmt.Errorf("%w: %w", ErrFailedToDetermineIfMaintenanceWindowIsActive, err) + moduleTemplateInfo.ModuleTemplate = nil + return moduleTemplateInfo + } + + if !active { + moduleTemplateInfo.Err = ErrWaitingForNextMaintenanceWindow + moduleTemplateInfo.ModuleTemplate = nil + return moduleTemplateInfo + } + + return moduleTemplateInfo +} + func ValidateTemplateMode(template ModuleTemplateInfo, kyma *v1beta2.Kyma, ) ModuleTemplateInfo { @@ -196,3 +315,8 @@ func filterVersion(version *semver.Version) *semver.Version { version.Major(), version.Minor(), version.Patch())) return filteredVersion } + +// TemplateNameMatch checks if a module template matches the given name. +func TemplateNameMatch(template *v1beta2.ModuleTemplate, name string) bool { + return template.Spec.ModuleName == name +} diff --git a/internal/templatelookup/regular_test.go b/internal/templatelookup/regular_test.go new file mode 100644 index 0000000000..8ff3efd256 --- /dev/null +++ b/internal/templatelookup/regular_test.go @@ -0,0 +1,308 @@ +package templatelookup_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + machineryruntime "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup/common" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" +) + +// TestSetup provides a simplified way to create test scenarios for templatelookup. +type TestSetup struct { + moduleTemplate *v1beta2.ModuleTemplate + moduleReleaseMeta *v1beta2.ModuleReleaseMeta + kyma *v1beta2.Kyma + client client.Client +} + +// NewTestSetup creates a new test setup with sensible defaults. +func NewTestSetup() *TestSetup { + scheme := machineryruntime.NewScheme() + _ = v1beta2.AddToScheme(scheme) + + return &TestSetup{ + client: fake.NewClientBuilder().WithScheme(scheme).Build(), + } +} + +// WithMandatoryModule sets up a mandatory module scenario. +func (ts *TestSetup) WithMandatoryModule(moduleName, version string) *TestSetup { + ts.moduleTemplate = builder.NewModuleTemplateBuilder(). + WithName(moduleName + "-" + version). + WithNamespace("test-namespace"). + WithModuleName(moduleName). + WithVersion(version). + Build() + + ts.moduleReleaseMeta = builder.NewModuleReleaseMetaBuilder(). + WithName(moduleName). + WithNamespace("test-namespace"). + WithModuleName(moduleName). + WithMandatory(version). + Build() + + ts.kyma = builder.NewKymaBuilder(). + WithNamespace("test-namespace"). + Build() + + return ts +} + +// WithChannelModule sets up a channel-based module scenario. +func (ts *TestSetup) WithChannelModule(moduleName, channel, version string) *TestSetup { + ts.moduleTemplate = builder.NewModuleTemplateBuilder(). + WithName(moduleName + "-" + version). + WithNamespace("test-namespace"). + WithModuleName(moduleName). + WithVersion(version). + Build() + + ts.moduleReleaseMeta = builder.NewModuleReleaseMetaBuilder(). + WithName(moduleName). + WithNamespace("test-namespace"). + WithModuleName(moduleName). + WithSingleModuleChannelAndVersions(channel, version). + Build() + + ts.kyma = builder.NewKymaBuilder(). + WithNamespace("test-namespace"). + WithChannel(channel). + Build() + + return ts +} + +// WithMissingTemplate creates a scenario where the module template doesn't exist. +func (ts *TestSetup) WithMissingTemplate(moduleName, channel, version string) *TestSetup { + // Only create ModuleReleaseMeta, no ModuleTemplate + ts.moduleReleaseMeta = builder.NewModuleReleaseMetaBuilder(). + WithName(moduleName). + WithNamespace("test-namespace"). + WithModuleName(moduleName). + WithSingleModuleChannelAndVersions(channel, version). + Build() + + ts.kyma = builder.NewKymaBuilder(). + WithNamespace("test-namespace"). + WithChannel(channel). + Build() + + return ts +} + +// Build creates the client with all configured objects and returns it. +func (ts *TestSetup) Build() client.Client { + scheme := machineryruntime.NewScheme() + _ = v1beta2.AddToScheme(scheme) + + objects := make([]client.Object, 0) + if ts.moduleTemplate != nil { + objects = append(objects, ts.moduleTemplate) + } + if ts.moduleReleaseMeta != nil { + objects = append(objects, ts.moduleReleaseMeta) + } + if ts.kyma != nil { + objects = append(objects, ts.kyma) + } + + return fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(objects...). + Build() +} + +// GetModuleInfo returns a ModuleInfo for testing. +func (ts *TestSetup) GetModuleInfo(moduleName string) *templatelookup.ModuleInfo { + return &templatelookup.ModuleInfo{ + Module: v1beta2.Module{ + Name: moduleName, + }, + } +} + +// GetKyma returns the configured Kyma object. +func (ts *TestSetup) GetKyma() *v1beta2.Kyma { + return ts.kyma +} + +// GetModuleReleaseMeta returns the configured ModuleReleaseMeta. +func (ts *TestSetup) GetModuleReleaseMeta() *v1beta2.ModuleReleaseMeta { + return ts.moduleReleaseMeta +} + +// ExecuteLookupModuleTemplate is a simplified test helper for LookupModuleTemplate. +func ExecuteLookupModuleTemplate(t *testing.T, setup *TestSetup, moduleName string) templatelookup.ModuleTemplateInfo { + t.Helper() + client := setup.Build() + moduleInfo := setup.GetModuleInfo(moduleName) + kyma := setup.GetKyma() + moduleReleaseMeta := setup.GetModuleReleaseMeta() + + return templatelookup.LookupModuleTemplate(t.Context(), client, moduleInfo, kyma, moduleReleaseMeta) +} + +// TestLookupModuleTemplate covers the core LookupModuleTemplate functionality. +func TestLookupModuleTemplate(t *testing.T) { + tests := []struct { + name string + setupFunc func() *TestSetup + moduleName string + expectError bool + expectNil bool + }{ + { + name: "mandatory module succeeds", + setupFunc: func() *TestSetup { + return NewTestSetup().WithMandatoryModule("test-module", "1.0.0") + }, + moduleName: "test-module", + expectError: false, + expectNil: false, + }, + { + name: "channel module succeeds", + setupFunc: func() *TestSetup { + return NewTestSetup().WithChannelModule("test-module", "stable", "1.0.0") + }, + moduleName: "test-module", + expectError: false, + expectNil: false, + }, + { + name: "missing template fails gracefully", + setupFunc: func() *TestSetup { + return NewTestSetup().WithMissingTemplate("test-module", "stable", "1.0.0") + }, + moduleName: "test-module", + expectError: true, + expectNil: true, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + setup := testCase.setupFunc() + result := ExecuteLookupModuleTemplate(t, setup, testCase.moduleName) + + if testCase.expectError { + require.Error(t, result.Err) + } else { + require.NoError(t, result.Err) + } + + if testCase.expectNil { + assert.Nil(t, result.ModuleTemplate) + } else { + assert.NotNil(t, result.ModuleTemplate) + assert.Contains(t, result.Name, testCase.moduleName) + } + }) + } +} + +// TestValidateTemplateMode covers template validation logic. +func TestValidateTemplateMode(t *testing.T) { + tests := []struct { + name string + template templatelookup.ModuleTemplateInfo + kyma *v1beta2.Kyma + wantErr error + }{ + { + name: "error propagation works", + template: templatelookup.ModuleTemplateInfo{ + Err: templatelookup.ErrTemplateNotAllowed, + }, + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + { + name: "internal module blocked for non-internal kyma", + template: templatelookup.ModuleTemplateInfo{ + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithLabel(shared.InternalLabel, "true").Build(), + }, + kyma: builder.NewKymaBuilder(). + WithLabel(shared.InternalLabel, "false"). + Build(), + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + { + name: "beta module blocked for non-beta kyma", + template: templatelookup.ModuleTemplateInfo{ + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithLabel(shared.BetaLabel, "true").Build(), + }, + kyma: builder.NewKymaBuilder(). + WithLabel(shared.BetaLabel, "false"). + Build(), + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + { + name: "mandatory module blocked", + template: templatelookup.ModuleTemplateInfo{ + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithMandatory(true).Build(), + }, + kyma: builder.NewKymaBuilder().Build(), + wantErr: common.ErrNoTemplatesInListResult, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + result := templatelookup.ValidateTemplateMode(testCase.template, testCase.kyma) + require.ErrorIs(t, result.Err, testCase.wantErr) + }) + } +} + +// TestTemplateNameMatch covers the template name matching utility. +func TestTemplateNameMatch(t *testing.T) { + tests := []struct { + name string + templateName string + targetName string + want bool + }{ + { + name: "empty name returns false", + templateName: "", + targetName: "module1", + want: false, + }, + { + name: "different names return false", + templateName: "module2", + targetName: "module1", + want: false, + }, + { + name: "matching names return true", + templateName: "module1", + targetName: "module1", + want: true, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + template := v1beta2.ModuleTemplate{ + Spec: v1beta2.ModuleTemplateSpec{ + ModuleName: testCase.templateName, + }, + } + result := templatelookup.TemplateNameMatch(&template, testCase.targetName) + assert.Equal(t, testCase.want, result) + }) + } +} diff --git a/pkg/module/common/module.go b/pkg/module/common/module.go index 94ef4bdf0e..400bd9d0e3 100644 --- a/pkg/module/common/module.go +++ b/pkg/module/common/module.go @@ -10,7 +10,7 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" ) type ( diff --git a/pkg/module/common/module_test.go b/pkg/module/common/module_test.go index 5e9184367e..ff3a7a04ee 100644 --- a/pkg/module/common/module_test.go +++ b/pkg/module/common/module_test.go @@ -7,8 +7,8 @@ import ( apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" ) func TestApplyDefaultMetaToManifest_WhenCalledWithEmptyKymaName_ReturnsEmptyKymaLabel(t *testing.T) { diff --git a/pkg/module/sync/runner.go b/pkg/module/sync/runner.go index f23d578e06..d044d8c7a8 100644 --- a/pkg/module/sync/runner.go +++ b/pkg/module/sync/runner.go @@ -14,10 +14,10 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/common" "github.com/kyma-project/lifecycle-manager/pkg/log" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/util" ) diff --git a/pkg/module/sync/runner_test.go b/pkg/module/sync/runner_test.go index 5de6558d78..49ac1e6dad 100644 --- a/pkg/module/sync/runner_test.go +++ b/pkg/module/sync/runner_test.go @@ -8,9 +8,9 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common" "github.com/kyma-project/lifecycle-manager/pkg/module/sync" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" ) func TestNeedToUpdate(t *testing.T) { diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy.go deleted file mode 100644 index 815be5bff1..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy.go +++ /dev/null @@ -1,134 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - "errors" - "fmt" - - "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/log" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" -) - -var ErrNotDefaultChannelAllowed = errors.New("specifying no default channel is not allowed") - -// ByChannelStrategy looks up the module template for a given channel-based installation. -type ByChannelStrategy struct { - client client.Reader -} - -func NewByChannelStrategy(client client.Reader) ByChannelStrategy { - return ByChannelStrategy{client: client} -} - -func (ByChannelStrategy) IsResponsible( - moduleInfo *templatelookup.ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) bool { - if moduleReleaseMeta != nil { - return false - } - - if moduleInfo.IsInstalledByVersion() { - return false - } - - return true -} - -func (s ByChannelStrategy) Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - kyma *v1beta2.Kyma, - _ *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - desiredChannel := getDesiredChannel(moduleInfo.Channel, kyma.Spec.Channel) - info := templatelookup.ModuleTemplateInfo{ - DesiredChannel: desiredChannel, - } - - template, err := s.filterTemplatesByChannel(ctx, moduleInfo.Name, desiredChannel) - if err != nil { - info.Err = err - return info - } - - actualChannel := template.Spec.Channel - if actualChannel == "" { - info.Err = fmt.Errorf( - "no channel found on template for module: %s: %w", - moduleInfo.Name, ErrNotDefaultChannelAllowed, - ) - return info - } - - logUsedChannel(ctx, moduleInfo.Name, actualChannel, kyma.Spec.Channel) - info.ModuleTemplate = template - return info -} - -func (s ByChannelStrategy) filterTemplatesByChannel(ctx context.Context, name, desiredChannel string) ( - *v1beta2.ModuleTemplate, error, -) { - templateList := &v1beta2.ModuleTemplateList{} - err := s.client.List(ctx, templateList) - if err != nil { - return nil, fmt.Errorf("failed to list module templates on lookup: %w", err) - } - - var filteredTemplates []*v1beta2.ModuleTemplate - for _, template := range templateList.Items { - if TemplateNameMatch(&template, name) && template.Spec.Channel == desiredChannel { - filteredTemplates = append(filteredTemplates, &template) - continue - } - } - - if len(filteredTemplates) > 1 { - return nil, newMoreThanOneTemplateCandidateErr(name, templateList.Items) - } - - if len(filteredTemplates) == 0 { - return nil, fmt.Errorf("%w: for module %s in channel %s ", - common.ErrNoTemplatesInListResult, name, desiredChannel) - } - - return filteredTemplates[0], nil -} - -func getDesiredChannel(moduleChannel, globalChannel string) string { - var desiredChannel string - - switch { - case moduleChannel != "": - desiredChannel = moduleChannel - case globalChannel != "": - desiredChannel = globalChannel - default: - desiredChannel = v1beta2.DefaultChannel - } - - return desiredChannel -} - -func logUsedChannel(ctx context.Context, name string, actualChannel string, defaultChannel string) { - logger := logf.FromContext(ctx) - if actualChannel != defaultChannel { - logger.V(log.DebugLevel).Info( - fmt.Sprintf( - "using %s (instead of %s) for module %s", - actualChannel, defaultChannel, name, - ), - ) - } else { - logger.V(log.DebugLevel).Info( - fmt.Sprintf( - "using %s for module %s", - actualChannel, name, - ), - ) - } -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go deleted file mode 100644 index acc0e0b4f6..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" -) - -func Test_ByChannelStrategy_IsResponsible_ReturnsTrue(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithChannel("regular").Enabled().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) - - responsible := byChannelStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.True(t, responsible) -} - -func Test_ByChannelStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithChannel("regular").Enabled().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder().Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) - - responsible := byChannelStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.False(t, responsible) -} - -func Test_ByChannelStrategy_IsResponsible_ReturnsFalse_WhenInstalledByVersion(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithVersion("1.0.0").Enabled().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) - - responsible := byChannelStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.False(t, responsible) -} - -func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - WithChannel("regular"). - Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) - require.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.Spec.Channel) -} - -func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo_UsingGlobalChannel(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").Enabled().Build() - kyma := builder.NewKymaBuilder().WithChannel("fast").Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - WithChannel("fast"). - Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) - require.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.Spec.Channel) -} - -func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo_UsingDefaultChannel(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - WithChannel("regular"). - Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) - require.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.Spec.Channel) -} - -func Test_ByChannelStrategy_Lookup_WhenNoModuleTemplateFound(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient(&v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{}, - })) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "no templates were found: for module test-module in channel regular") -} - -func Test_ByChannelStrategy_Lookup_WhenFailedToListModuleTemplates(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(&failedClientStub{}) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "failed to list module templates on lookup") -} - -func Test_ByChannelStrategy_Lookup_WhenMoreThanOneModuleTemplateFound(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - firstModuleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-regular"). - WithModuleName("test-module"). - WithChannel("regular"). - Build() - secondModuleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-regular-2"). - WithModuleName("test-module"). - WithChannel("regular"). - Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *firstModuleTemplate, - *secondModuleTemplate, - }, - }, - )) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains( - t, - moduleTemplateInfo.Err, - "no unique template could be identified: more than one module template found for module: test-module, "+ - "candidates: [test-module-regular test-module-regular-2]", - ) -} - -func Test_ByChannelStrategy_Lookup_WhenModuleTemplateHasNoChannel(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - Build() - byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byChannelStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "no templates were found: for module test-module in channel regular") -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy.go deleted file mode 100644 index 5bb47f1739..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy.go +++ /dev/null @@ -1,62 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" -) - -// ByModuleReleaseMetaStrategy looks up the module template via the module release meta. -// It only supports channel-based installation. -type ByModuleReleaseMetaStrategy struct { - client client.Reader -} - -func NewByModuleReleaseMetaStrategy(client client.Reader) ByModuleReleaseMetaStrategy { - return ByModuleReleaseMetaStrategy{client: client} -} - -func (ByModuleReleaseMetaStrategy) IsResponsible( - _ *templatelookup.ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) bool { - return moduleReleaseMeta != nil -} - -func (s ByModuleReleaseMetaStrategy) Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - kyma *v1beta2.Kyma, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - moduleTemplateInfo := templatelookup.ModuleTemplateInfo{} - moduleTemplateInfo.DesiredChannel = getDesiredChannel(moduleInfo.Channel, kyma.Spec.Channel) - - var desiredModuleVersion string - var err error - if moduleReleaseMeta.Spec.Mandatory != nil { - desiredModuleVersion, err = templatelookup.GetMandatoryVersionForModule(moduleReleaseMeta) - } else { - desiredModuleVersion, err = templatelookup.GetChannelVersionForModule(moduleReleaseMeta, - moduleTemplateInfo.DesiredChannel) - } - if err != nil { - moduleTemplateInfo.Err = err - return moduleTemplateInfo - } - - template, err := getTemplateByVersion(ctx, - s.client, - moduleInfo.Name, - desiredModuleVersion, - kyma.Namespace) - if err != nil { - moduleTemplateInfo.Err = err - return moduleTemplateInfo - } - - moduleTemplateInfo.ModuleTemplate = template - return moduleTemplateInfo -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go deleted file mode 100644 index 58fee1137a..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - machineryruntime "k8s.io/apimachinery/pkg/runtime" - machineryutilruntime "k8s.io/apimachinery/pkg/util/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - "github.com/kyma-project/lifecycle-manager/api" - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" -) - -func Test_ByModuleReleaseMetaStrategy_IsResponsible_ReturnsTrue(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithChannel("regular").Enabled().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder().Build() - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil) - - responsible := byMRMStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.True(t, responsible) -} - -func Test_ByModuleReleaseMetaStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithVersion("regular").Enabled().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil) - - responsible := byMRMStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.False(t, responsible) -} - -func Test_ByModuleReleaseMeta_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). - WithModuleName("test-module"). - WithName("test-module"). - WithModuleChannelAndVersions([]v1beta2.ChannelVersionAssignment{ - { - Channel: "regular", - Version: "1.0.0", - }, - }). - Build() - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - Build() - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byMRMStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) - require.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.Spec.Channel) -} - -func Test_ByModuleReleaseMeta_Strategy_Lookup_WhenGetChannelVersionForModuleReturnsError(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). - WithModuleName("test-module"). - WithName("test-module"). - WithModuleChannelAndVersions([]v1beta2.ChannelVersionAssignment{ - { - Channel: "regular", - Version: "1.0.0", - }, - }). - Build() - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - Build() - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byMRMStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "failed to get module template: moduletemplates.operator.kyma-project.io \"test-module-1.0.0\" not found") -} - -func Test_ByModuleReleaseMeta_Strategy_Lookup_WhenGetTemplateByVersionReturnsError(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). - WithModuleName("test-module"). - WithName("test-module"). - Build() - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - Build() - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byMRMStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, "no channels found for module: test-module") -} - -func Test_ByModuleReleaseMeta_Strategy_Lookup_WhenMandatoryModuleActivated_ReturnsModuleTemplateInfo(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() - kyma := builder.NewKymaBuilder().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). - WithModuleName("test-module"). - WithName("test-module"). - WithMandatory("1.0.0"). - Build() - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0"). - WithModuleName("test-module"). - WithMandatory(true). - WithVersion("1.0.0"). - Build() - byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byMRMStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) -} - -func fakeClient(mts *v1beta2.ModuleTemplateList) client.Client { - scheme := machineryruntime.NewScheme() - machineryutilruntime.Must(api.AddToScheme(scheme)) - - return fake.NewClientBuilder().WithScheme(scheme).WithLists(mts).Build() -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go deleted file mode 100644 index aede4a0300..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go +++ /dev/null @@ -1,82 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - "fmt" - - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kyma-project/lifecycle-manager/api/shared" - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" -) - -// ByVersionStrategy looks up the module template for a given version-based installation. -type ByVersionStrategy struct { - client client.Reader -} - -func NewByVersionStrategy(client client.Reader) ByVersionStrategy { - return ByVersionStrategy{client: client} -} - -func (ByVersionStrategy) IsResponsible( - moduleInfo *templatelookup.ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) bool { - if moduleReleaseMeta != nil { - return false - } - - if !moduleInfo.IsInstalledByVersion() { - return false - } - - return true -} - -func (s ByVersionStrategy) Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - _ *v1beta2.Kyma, - _ *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - info := templatelookup.ModuleTemplateInfo{ - DesiredChannel: string(shared.NoneChannel), - } - template, err := s.filterTemplatesByVersion(ctx, moduleInfo.Name, moduleInfo.Version) - if err != nil { - info.Err = err - return info - } - - info.ModuleTemplate = template - return info -} - -func (s ByVersionStrategy) filterTemplatesByVersion(ctx context.Context, name, version string) ( - *v1beta2.ModuleTemplate, error, -) { - templateList := &v1beta2.ModuleTemplateList{} - err := s.client.List(ctx, templateList) - if err != nil { - return nil, fmt.Errorf("failed to list module templates on lookup: %w", err) - } - - var filteredTemplates []*v1beta2.ModuleTemplate - for _, template := range templateList.Items { - if TemplateNameMatch(&template, - name) && shared.NoneChannel.Equals(template.Spec.Channel) && template.Spec.Version == version { - filteredTemplates = append(filteredTemplates, &template) - continue - } - } - if len(filteredTemplates) > 1 { - return nil, newMoreThanOneTemplateCandidateErr(name, templateList.Items) - } - if len(filteredTemplates) == 0 { - return nil, fmt.Errorf("%w: for module %s in version %s", - common.ErrNoTemplatesInListResult, name, version) - } - return filteredTemplates[0], nil -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go deleted file mode 100644 index 61ce68b373..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "context" - "errors" - "testing" - - "github.com/stretchr/testify/require" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" -) - -func Test_ByVersionStrategy_IsResponsible_ReturnsTrue(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithVersion("1.0.0").Enabled().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) - - responsible := byVersionStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.True(t, responsible) -} - -func Test_ByVersionStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithVersion("1.0.0").Enabled().Build() - moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder().Build() - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) - - responsible := byVersionStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.False(t, responsible) -} - -func Test_ByVersionStrategy_IsResponsible_ReturnsFalse_WhenNotInstalledByVersion(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithVersion("").WithChannel("regular").Enabled().Build() - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) - - responsible := byVersionStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) - - require.False(t, responsible) -} - -func Test_ByVersion_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() - var kyma *v1beta2.Kyma = nil - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - WithChannel("none"). - Build() - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *moduleTemplate, - }, - }, - )) - - moduleTemplateInfo := byVersionStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Equal(t, moduleTemplate.Name, moduleTemplateInfo.Name) - require.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.Spec.ModuleName) - require.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.Spec.Version) - require.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.Spec.Channel) -} - -func Test_ByVersion_Strategy_Lookup_WhenMoreThanOneModuleTemplateFound(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() - var kyma *v1beta2.Kyma = nil - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - firstModuleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - WithChannel("none"). - Build() - secondModuleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-1.0.0-duplicate"). - WithModuleName("test-module"). - WithVersion("1.0.0"). - WithChannel("none"). - Build() - - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{ - *firstModuleTemplate, - *secondModuleTemplate, - }, - }, - )) - - moduleTemplateInfo := byVersionStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains( - t, - moduleTemplateInfo.Err, - "no unique template could be identified: more than one module template found for module: test-module, "+ - "candidates: [test-module-1.0.0 test-module-1.0.0-duplicate]", - ) -} - -func Test_ByVersion_Strategy_Lookup_WhenFailedToListModuleTemplates(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() - var kyma *v1beta2.Kyma = nil - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(&failedClientStub{}) - - moduleTemplateInfo := byVersionStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "failed to list module templates on lookup") -} - -func Test_ByVersion_Strategy_Lookup_WhenNoModuleTemplateFound(t *testing.T) { - moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() - var kyma *v1beta2.Kyma = nil - var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil - - byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( - &v1beta2.ModuleTemplateList{ - Items: []v1beta2.ModuleTemplate{}, - }, - )) - - moduleTemplateInfo := byVersionStrategy.Lookup(t.Context(), moduleInfo, kyma, moduleReleaseMeta) - - require.NotNil(t, moduleTemplateInfo) - require.Nil(t, moduleTemplateInfo.ModuleTemplate) - require.ErrorContains(t, moduleTemplateInfo.Err, - "no templates were found: for module test-module in version 1.0.0") -} - -type moduleInfoBuilder struct { - moduleInfo *templatelookup.ModuleInfo -} - -func newModuleInfoBuilder() moduleInfoBuilder { - return moduleInfoBuilder{ - moduleInfo: &templatelookup.ModuleInfo{ - Module: v1beta2.Module{}, - }, - } -} - -func (b moduleInfoBuilder) WithName(name string) moduleInfoBuilder { - b.moduleInfo.Name = name - return b -} - -func (b moduleInfoBuilder) WithVersion(version string) moduleInfoBuilder { - b.moduleInfo.Version = version - return b -} - -func (b moduleInfoBuilder) WithChannel(channel string) moduleInfoBuilder { - b.moduleInfo.Channel = channel - return b -} - -func (b moduleInfoBuilder) Enabled() moduleInfoBuilder { - b.moduleInfo.Enabled = true - return b -} - -func (b moduleInfoBuilder) Build() *templatelookup.ModuleInfo { - return b.moduleInfo -} - -type failedClientStub struct { - client.Client -} - -func (c *failedClientStub) List(_ context.Context, _ client.ObjectList, _ ...client.ListOption) error { - return errors.New("failed to list module templates") -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/common.go b/pkg/templatelookup/moduletemplateinfolookup/common.go deleted file mode 100644 index 9d144ec072..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/common.go +++ /dev/null @@ -1,44 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - "fmt" - - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" -) - -func TemplateNameMatch(template *v1beta2.ModuleTemplate, name string) bool { - return template.Spec.ModuleName == name -} - -func newMoreThanOneTemplateCandidateErr(moduleName string, templates []v1beta2.ModuleTemplate) error { - candidates := make([]string, len(templates)) - for i, candidate := range templates { - candidates[i] = candidate.GetName() - } - - return fmt.Errorf("%w: more than one module template found for module: %s, candidates: %v", - common.ErrTemplateNotIdentified, moduleName, candidates) -} - -func getTemplateByVersion(ctx context.Context, - clnt client.Reader, - moduleName, - moduleVersion, - namespace string, -) (*v1beta2.ModuleTemplate, error) { - moduleTemplate := &v1beta2.ModuleTemplate{} - - moduleTemplateName := fmt.Sprintf("%s-%s", moduleName, moduleVersion) - if err := clnt.Get(ctx, client.ObjectKey{ - Name: moduleTemplateName, - Namespace: namespace, - }, moduleTemplate); err != nil { - return nil, fmt.Errorf("failed to get module template: %w", err) - } - - return moduleTemplate, nil -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/common_test.go b/pkg/templatelookup/moduletemplateinfolookup/common_test.go deleted file mode 100644 index ece482b21e..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/common_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" -) - -func Test_TemplateNameMatch_WhenModuleNameFieldIsMatching(t *testing.T) { - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - Build() - - isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "test-module") - assert.True(t, isNameMatching) -} - -func Test_TemplateNameMatch_WhenModuleNameFieldIsNotMatching(t *testing.T) { - moduleTemplate := builder.NewModuleTemplateBuilder(). - WithModuleName("test-module"). - Build() - - isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "module") - assert.False(t, isNameMatching) -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/strategies.go b/pkg/templatelookup/moduletemplateinfolookup/strategies.go deleted file mode 100644 index d331f94f3f..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/strategies.go +++ /dev/null @@ -1,52 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - "errors" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" -) - -var ErrNoResponsibleStrategy = errors.New("failed to find responsible module template lookup strategy") - -type ModuleTemplateInfoLookupStrategy interface { - // IsResponsible checks if the strategy is responsible for the given module installation. - IsResponsible(moduleInfo *templatelookup.ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, - ) bool - // Lookup looks up the required module template. - Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - kyma *v1beta2.Kyma, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, - ) templatelookup.ModuleTemplateInfo -} - -// ModuleTemplateInfoLookupStrategies is a strategy that aggregates multiple ModuleTemplateInfoLookupStrategies. -// It iterates over the strategies and uses the first one that is responsible for the given module info. -type ModuleTemplateInfoLookupStrategies struct { - strategies []ModuleTemplateInfoLookupStrategy -} - -func NewModuleTemplateInfoLookupStrategies( - strategies []ModuleTemplateInfoLookupStrategy, -) ModuleTemplateInfoLookupStrategies { - return ModuleTemplateInfoLookupStrategies{strategies: strategies} -} - -func (s ModuleTemplateInfoLookupStrategies) Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - kyma *v1beta2.Kyma, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - for _, strategy := range s.strategies { - if strategy.IsResponsible(moduleInfo, moduleReleaseMeta) { - return strategy.Lookup(ctx, moduleInfo, kyma, moduleReleaseMeta) - } - } - - return templatelookup.ModuleTemplateInfo{ - Err: ErrNoResponsibleStrategy, - } -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/strategies_test.go b/pkg/templatelookup/moduletemplateinfolookup/strategies_test.go deleted file mode 100644 index 0a040bb581..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/strategies_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" -) - -func Test_ModuleTemplateInfoLookupStrategies_Lookup_CallsResponsibleStrategy(t *testing.T) { - nonResponsibleStrategy := newLookupStrategyStub(false) - responsibleStrategy := newLookupStrategyStub(true) - strategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - &nonResponsibleStrategy, - &responsibleStrategy, - }, - ) - - moduleTemplateInfo := strategies.Lookup(t.Context(), nil, nil, nil) - - assert.True(t, responsibleStrategy.called) - assert.False(t, nonResponsibleStrategy.called) - require.NoError(t, moduleTemplateInfo.Err) -} - -func Test_ModuleTemplateInfoLookupStrategies_Lookup_CallsFirstResponsibleStrategy(t *testing.T) { - nonResponsibleStrategy := newLookupStrategyStub(false) - responsibleStrategy := newLookupStrategyStub(true) - responsibleStrategy2 := newLookupStrategyStub(true) - strategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - &nonResponsibleStrategy, - &responsibleStrategy, - &responsibleStrategy2, - }, - ) - - moduleTemplateInfo := strategies.Lookup(t.Context(), nil, nil, nil) - - assert.True(t, responsibleStrategy.called) - assert.False(t, responsibleStrategy2.called) - assert.False(t, nonResponsibleStrategy.called) - require.NoError(t, moduleTemplateInfo.Err) -} - -func Test_ModuleTemplateInfoLookupStrategies_Lookup_ReturnsFailureWhenNoStrategyResponsible(t *testing.T) { - nonResponsibleStrategy := newLookupStrategyStub(false) - strategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - &nonResponsibleStrategy, - }, - ) - - moduleTemplateInfo := strategies.Lookup(t.Context(), nil, nil, nil) - - assert.False(t, nonResponsibleStrategy.called) - require.ErrorIs(t, moduleTemplateInfo.Err, moduletemplateinfolookup.ErrNoResponsibleStrategy) -} - -func Test_ModuleTemplateInfoLookupStrategies_Lookup_ReturnsFailureWhenNoStrategies(t *testing.T) { - strategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{}, - ) - - moduleTemplateInfo := strategies.Lookup(t.Context(), nil, nil, nil) - - require.ErrorIs(t, moduleTemplateInfo.Err, moduletemplateinfolookup.ErrNoResponsibleStrategy) -} - -func newLookupStrategyStub(responsible bool) LookupStrategyStub { - return LookupStrategyStub{ - responsible: responsible, - } -} - -type LookupStrategyStub struct { - responsible bool - called bool -} - -func (s *LookupStrategyStub) Lookup(ctx context.Context, - _ *templatelookup.ModuleInfo, - _ *v1beta2.Kyma, - _ *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - s.called = true - return templatelookup.ModuleTemplateInfo{} -} - -func (s *LookupStrategyStub) IsResponsible(_ *templatelookup.ModuleInfo, _ *v1beta2.ModuleReleaseMeta, -) bool { - return s.responsible -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator.go b/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator.go deleted file mode 100644 index 11e9a1b25e..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator.go +++ /dev/null @@ -1,76 +0,0 @@ -package moduletemplateinfolookup - -import ( - "context" - "errors" - "fmt" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" -) - -var ( - ErrWaitingForNextMaintenanceWindow = errors.New( - "waiting for next maintenance window to update module version", - ) - ErrFailedToDetermineIfMaintenanceWindowIsActive = errors.New("failed to determine if maintenance window is active") -) - -type MaintenanceWindow interface { - IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool - IsActive(kyma *v1beta2.Kyma) (bool, error) -} - -type WithMaintenanceWindowDecorator struct { - maintenanceWindow MaintenanceWindow - decorated ModuleTemplateInfoLookupStrategy -} - -func NewWithMaintenanceWindowDecorator(maintenanceWindow MaintenanceWindow, - decorated ModuleTemplateInfoLookupStrategy, -) WithMaintenanceWindowDecorator { - return WithMaintenanceWindowDecorator{ - maintenanceWindow: maintenanceWindow, - decorated: decorated, - } -} - -func (p WithMaintenanceWindowDecorator) IsResponsible(moduleInfo *templatelookup.ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) bool { - return p.decorated.IsResponsible(moduleInfo, moduleReleaseMeta) -} - -func (p WithMaintenanceWindowDecorator) Lookup(ctx context.Context, - moduleInfo *templatelookup.ModuleInfo, - kyma *v1beta2.Kyma, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - moduleTemplateInfo := p.decorated.Lookup(ctx, - moduleInfo, - kyma, - moduleReleaseMeta) - - // decorated returns an error case => return immediately - if moduleTemplateInfo.ModuleTemplate == nil || moduleTemplateInfo.Err != nil { - return moduleTemplateInfo - } - - if !p.maintenanceWindow.IsRequired(moduleTemplateInfo.ModuleTemplate, kyma) { - return moduleTemplateInfo - } - - active, err := p.maintenanceWindow.IsActive(kyma) - if err != nil { - moduleTemplateInfo.Err = fmt.Errorf("%w: %w", ErrFailedToDetermineIfMaintenanceWindowIsActive, err) - moduleTemplateInfo.ModuleTemplate = nil - return moduleTemplateInfo - } - - if !active { - moduleTemplateInfo.Err = ErrWaitingForNextMaintenanceWindow - moduleTemplateInfo.ModuleTemplate = nil - return moduleTemplateInfo - } - return moduleTemplateInfo -} diff --git a/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator_test.go b/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator_test.go deleted file mode 100644 index 3a988793b9..0000000000 --- a/pkg/templatelookup/moduletemplateinfolookup/with_maintenance_window_decorator_test.go +++ /dev/null @@ -1,224 +0,0 @@ -package moduletemplateinfolookup_test - -import ( - "context" - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" -) - -func Test_WithMWDecorator_IsResponsible_CallsDecoratedIsResponsible(t *testing.T) { - decorated := &lookupStrategyStub{ - responsible: true, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(nil, decorated) - - responsible := withMaintenanceWindowDecorator.IsResponsible(nil, nil) - - assert.True(t, decorated.called) - assert.True(t, responsible) -} - -func Test_WithMWDecorator_Lookup_ReturnsModuleTemplateInfo_WhenDecoratedLookupReturnsModuleTemplateInfoWithError( - t *testing.T, -) { - maintenanceWindow := &maintenanceWindowStub{} - expectedModuleTemplateInfo := templatelookup.ModuleTemplateInfo{ - Err: errors.New("test error"), - } - decorated := &lookupStrategyStub{ - moduleTemplateInfo: expectedModuleTemplateInfo, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.False(t, maintenanceWindow.requiredCalled) - assert.False(t, maintenanceWindow.activeCalled) - assert.Equal(t, expectedModuleTemplateInfo, moduleTemplateInfo) -} - -func Test_WithMWDecorator_Lookup_ReturnsModuleTemplateInfo_WhenDecoratedLookupReturnsNilTemplate(t *testing.T) { - maintenanceWindow := &maintenanceWindowStub{} - decorated := &lookupStrategyStub{ - moduleTemplateInfo: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: nil, - }, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.False(t, maintenanceWindow.requiredCalled) - assert.False(t, maintenanceWindow.activeCalled) - assert.Nil(t, moduleTemplateInfo.ModuleTemplate) -} - -func Test_WithMWDecorator_Lookup_ReturnsModuleTemplateInfo_WhenNoMWRequired(t *testing.T) { - maintenanceWindow := &maintenanceWindowStub{ - required: false, - } - expectedModuleTemplateInfo := templatelookup.ModuleTemplateInfo{ - DesiredChannel: "test", - ModuleTemplate: &v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - Channel: "test", - }, - }, - } - decorated := &lookupStrategyStub{ - moduleTemplateInfo: expectedModuleTemplateInfo, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.True(t, maintenanceWindow.requiredCalled) - assert.False(t, maintenanceWindow.activeCalled) - assert.Equal(t, expectedModuleTemplateInfo, moduleTemplateInfo) -} - -func Test_WithMWDecorator_Lookup_ReturnsError_WhenIsActiveReturnsError(t *testing.T) { - err := errors.New("test error") - maintenanceWindow := &maintenanceWindowStub{ - required: true, - err: err, - } - decorated := &lookupStrategyStub{ - moduleTemplateInfo: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: &v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - Channel: "test", - }, - }, - }, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.True(t, maintenanceWindow.requiredCalled) - assert.True(t, maintenanceWindow.activeCalled) - require.ErrorIs(t, moduleTemplateInfo.Err, moduletemplateinfolookup.ErrFailedToDetermineIfMaintenanceWindowIsActive) - require.ErrorIs(t, moduleTemplateInfo.Err, err) - assert.Nil(t, moduleTemplateInfo.ModuleTemplate) -} - -func Test_WithMWDecorator_Lookup_ReturnsError_WhenMWIsRequiredAndNotActive(t *testing.T) { - maintenanceWindow := &maintenanceWindowStub{ - required: true, - active: false, - } - decorated := &lookupStrategyStub{ - moduleTemplateInfo: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: &v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - Channel: "test", - }, - }, - }, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.True(t, maintenanceWindow.requiredCalled) - assert.True(t, maintenanceWindow.activeCalled) - require.ErrorIs(t, moduleTemplateInfo.Err, moduletemplateinfolookup.ErrWaitingForNextMaintenanceWindow) - assert.Nil(t, moduleTemplateInfo.ModuleTemplate) -} - -func Test_WithMWDecorator_Lookup_ReturnsModuleTemplateInfo_WhenMWIsRequiredAndActive(t *testing.T) { - maintenanceWindow := &maintenanceWindowStub{ - required: true, - active: true, - } - expectedModuleTemplateInfo := templatelookup.ModuleTemplateInfo{ - DesiredChannel: "test", - ModuleTemplate: &v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - Channel: "test", - }, - }, - } - decorated := &lookupStrategyStub{ - moduleTemplateInfo: expectedModuleTemplateInfo, - } - withMaintenanceWindowDecorator := moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow, - decorated) - - moduleTemplateInfo := withMaintenanceWindowDecorator.Lookup(t.Context(), - nil, - nil, - nil) - - assert.True(t, maintenanceWindow.requiredCalled) - assert.True(t, maintenanceWindow.activeCalled) - assert.Equal(t, expectedModuleTemplateInfo, moduleTemplateInfo) -} - -type lookupStrategyStub struct { - responsible bool - called bool - moduleTemplateInfo templatelookup.ModuleTemplateInfo -} - -func (s *lookupStrategyStub) IsResponsible(_ *templatelookup.ModuleInfo, _ *v1beta2.ModuleReleaseMeta) bool { - s.called = true - return s.responsible -} - -func (s *lookupStrategyStub) Lookup(_ context.Context, - _ *templatelookup.ModuleInfo, - _ *v1beta2.Kyma, - _ *v1beta2.ModuleReleaseMeta, -) templatelookup.ModuleTemplateInfo { - return s.moduleTemplateInfo -} - -type maintenanceWindowStub struct { - requiredCalled bool - required bool - activeCalled bool - active bool - err error -} - -func (s *maintenanceWindowStub) IsRequired(_ *v1beta2.ModuleTemplate, _ *v1beta2.Kyma) bool { - s.requiredCalled = true - return s.required -} - -func (s *maintenanceWindowStub) IsActive(_ *v1beta2.Kyma) (bool, error) { - s.activeCalled = true - if s.err != nil { - return false, s.err - } - return s.active, nil -} diff --git a/pkg/templatelookup/regular_test.go b/pkg/templatelookup/regular_test.go deleted file mode 100644 index 5cd75226d4..0000000000 --- a/pkg/templatelookup/regular_test.go +++ /dev/null @@ -1,1030 +0,0 @@ -package templatelookup_test - -import ( - "context" - "errors" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" - "ocm.software/ocm/api/ocm/compdesc" - ocmmetav1 "ocm.software/ocm/api/ocm/compdesc/meta/v1" - compdescv2 "ocm.software/ocm/api/ocm/compdesc/versions/v2" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/kyma-project/lifecycle-manager/api/shared" - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" - "github.com/kyma-project/lifecycle-manager/internal/descriptor/types" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" - "github.com/kyma-project/lifecycle-manager/pkg/testutils" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" -) - -const ( - version1 = "1.0.1" - version2 = "2.2.0" - version3 = "3.0.3" - - versionUpgradeErr = "as a higher version (" + version3 + ") of the module was previously installed" -) - -type FakeModuleTemplateReader struct { - templateList v1beta2.ModuleTemplateList - moduleReleaseMetaList v1beta2.ModuleReleaseMetaList -} - -func NewFakeModuleTemplateReader(templateList v1beta2.ModuleTemplateList, - moduleReleaseMetaList v1beta2.ModuleReleaseMetaList, -) *FakeModuleTemplateReader { - return &FakeModuleTemplateReader{ - templateList: templateList, - moduleReleaseMetaList: moduleReleaseMetaList, - } -} - -func (f *FakeModuleTemplateReader) List(_ context.Context, list client.ObjectList, _ ...client.ListOption) error { - castedList, ok := list.(*v1beta2.ModuleTemplateList) - if !ok { - return errors.New("list is not of type *v1beta2.ModuleTemplateList") - } - castedList.Items = append(castedList.Items, f.templateList.Items...) - return nil -} - -func (f *FakeModuleTemplateReader) Get(_ context.Context, objKey client.ObjectKey, obj client.Object, - _ ...client.GetOption, -) error { - notFoundErr := apierrors.NewNotFound(schema.GroupResource{}, objKey.Name) - if castedObj, ok := obj.(*v1beta2.ModuleReleaseMeta); ok { - for _, mrm := range f.moduleReleaseMetaList.Items { - if mrm.Name == objKey.Name { - *castedObj = mrm - return nil - } - } - - return notFoundErr - } else if castedObj, ok := obj.(*v1beta2.ModuleTemplate); ok { - for _, template := range f.templateList.Items { - if template.Name == objKey.Name { - *castedObj = template - return nil - } - } - return notFoundErr - } - - return nil -} - -func TestValidateTemplateMode_ForOldModuleTemplates(t *testing.T) { - tests := []struct { - name string - template templatelookup.ModuleTemplateInfo - kyma *v1beta2.Kyma - wantErr error - }{ - { - name: "When TemplateInfo contains Error, Then the output is same as input", - template: templatelookup.ModuleTemplateInfo{ - Err: templatelookup.ErrTemplateNotAllowed, - }, - wantErr: templatelookup.ErrTemplateNotAllowed, - }, - { - name: "When ModuleTemplate is internal but Kyma is not, Then result contains error", - template: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithLabel(shared.InternalLabel, "true").Build(), - }, - kyma: builder.NewKymaBuilder(). - WithLabel(shared.InternalLabel, "false"). - Build(), - wantErr: templatelookup.ErrTemplateNotAllowed, - }, - { - name: "When ModuleTemplate is beta but Kyma is not, Then result contains error", - template: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithLabel(shared.BetaLabel, "true").Build(), - }, - kyma: builder.NewKymaBuilder(). - WithLabel(shared.BetaLabel, "false"). - Build(), - wantErr: templatelookup.ErrTemplateNotAllowed, - }, - { - name: "When ModuleTemplate is mandatory, Then result contains error", - template: templatelookup.ModuleTemplateInfo{ - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithMandatory(true).Build(), - }, - kyma: builder.NewKymaBuilder().Build(), - wantErr: common.ErrNoTemplatesInListResult, - }, - } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - if got := templatelookup.ValidateTemplateMode(testCase.template, testCase.kyma); !errors.Is(got.Err, - testCase.wantErr) { - t.Errorf("ValidateTemplateMode() = %v, want %v", got, testCase.wantErr) - } - }) - } -} - -func Test_GetRegularTemplates_WhenInvalidModuleProvided(t *testing.T) { - tests := []struct { - name string - KymaSpec v1beta2.KymaSpec - KymaStatus v1beta2.KymaStatus - wantErr error - }{ - { - name: "When Module in Spec contains both Channel and Version, Then result contains error", - KymaSpec: v1beta2.KymaSpec{ - Modules: []v1beta2.Module{ - {Name: "Module1", Channel: "regular", Version: "v1.0"}, - }, - }, - wantErr: templatelookup.ErrInvalidModuleInSpec, - }, - { - name: "When Template not exists in Status, Then result contains error", - KymaStatus: v1beta2.KymaStatus{ - Modules: []v1beta2.ModuleStatus{ - { - Name: "Module1", - Channel: "regular", - Version: "v1.0", - Template: nil, - }, - }, - }, - wantErr: templatelookup.ErrInvalidModuleInStatus, - }, - } - - for _, tt := range tests { - test := tt - t.Run(tt.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup( - nil, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(nil), - moduletemplateinfolookup.NewByChannelStrategy(nil), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil), - }, - ), - ) - kyma := &v1beta2.Kyma{ - Spec: test.KymaSpec, - Status: test.KymaStatus, - } - got := lookup.GetRegularTemplates(t.Context(), kyma) - for _, err := range got { - if !errors.Is(err.Err, test.wantErr) { - t.Errorf("GetRegularTemplates() = %v, want %v", got, test.wantErr) - } - } - }) - } -} - -func TestTemplateLookup_GetRegularTemplates_WhenSwitchModuleChannel(t *testing.T) { - testModule := testutils.NewTestModule("module1", "new_channel") - - tests := []struct { - name string - kyma *v1beta2.Kyma - availableModuleTemplate v1beta2.ModuleTemplateList - availableModuleReleaseMeta v1beta2.ModuleReleaseMetaList - want templatelookup.ModuleTemplatesByModuleName - }{ - { - name: "When upgrade version during channel switch, " + - "then result contains no error, without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: v1beta2.DefaultChannel, - Version: version1, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, testModule.Channel, - version2), - availableModuleReleaseMeta: v1beta2.ModuleReleaseMetaList{}, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - }, - }, - }, - { - name: "When downgrade version during channel switch, Then result contains error, without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: v1beta2.DefaultChannel, - Version: version2, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, testModule.Channel, - version1), - availableModuleReleaseMeta: v1beta2.ModuleReleaseMetaList{}, - - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: templatelookup.ErrTemplateUpdateNotAllowed, - }, - }, - }, - { - name: "When upgrade version during channel switch, Then result contains no error, with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: v1beta2.DefaultChannel, - Version: version1, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, "", - version2), - availableModuleReleaseMeta: generateModuleReleaseMetaList(testModule.Name, - []v1beta2.ChannelVersionAssignment{ - {Channel: testModule.Channel, Version: version2}, - {Channel: v1beta2.DefaultChannel, Version: version1}, - }), - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - }, - }, - }, - { - name: "When downgrade version during channel switch, Then result contains error, with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Version: version2, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, "", - version1), - availableModuleReleaseMeta: generateModuleReleaseMetaList(testModule.Name, - []v1beta2.ChannelVersionAssignment{ - {Channel: testModule.Channel, Version: version1}, - }), - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: templatelookup.ErrTemplateUpdateNotAllowed, - }, - }, - }, - } - - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - reader := NewFakeModuleTemplateReader(testCase.availableModuleTemplate, testCase.availableModuleReleaseMeta) - lookup := templatelookup.NewTemplateLookup( - reader, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(reader), - moduletemplateinfolookup.NewByChannelStrategy(reader), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), - }, - ), - ) - got := lookup.GetRegularTemplates(t.Context(), testCase.kyma) - expected := len(testCase.want) - assert.Len(t, got, expected) - for key, module := range got { - wantModule, ok := testCase.want[key] - assert.True(t, ok) - assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) - require.ErrorIs(t, module.Err, wantModule.Err) - } - }) - } -} - -func TestTemplateLookup_GetRegularTemplates_WhenSwitchBetweenModuleVersions(t *testing.T) { - moduleToInstall := moduleToInstallByVersion("module1", version2) - - availableModuleTemplates := (&ModuleTemplateListBuilder{}). - Add(moduleToInstall.Name, "regular", version1). - Add(moduleToInstall.Name, "fast", version2). - Add(moduleToInstall.Name, "experimental", version3). - Add(moduleToInstall.Name, string(shared.NoneChannel), version1). - Add(moduleToInstall.Name, string(shared.NoneChannel), version2). - Add(moduleToInstall.Name, string(shared.NoneChannel), version3). - Build() - - availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - - tests := getRegularTemplatesTestCases{ - { - name: "When upgrade version, then result contains no error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: string(shared.NoneChannel), - Version: version1, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantChannel: string(shared.NoneChannel), - wantVersion: version2, - }, - { - name: "When downgrade version, then result contains error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: string(shared.NoneChannel), - Version: version3, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantErrContains: versionUpgradeErr, - }, - } - - executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, - moduleToInstall) -} - -func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromChannelToVersion(t *testing.T) { - moduleToInstall := moduleToInstallByVersion("module1", version2) - availableModuleTemplates := (&ModuleTemplateListBuilder{}). - Add(moduleToInstall.Name, "regular", version1). - Add(moduleToInstall.Name, "fast", version2). - Add(moduleToInstall.Name, "experimental", version3). - Add(moduleToInstall.Name, string(shared.NoneChannel), version1). - Add(moduleToInstall.Name, string(shared.NoneChannel), version2). - Add(moduleToInstall.Name, string(shared.NoneChannel), version3). - Build() - - availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - - tests := getRegularTemplatesTestCases{ - { - name: "When staying with the same version, then result contains no error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: "fast", - Version: version2, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantChannel: string(shared.NoneChannel), - wantVersion: version2, - }, - { - name: "When upgrade version, then result contains no error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: "regular", - Version: version1, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantChannel: string(shared.NoneChannel), - wantVersion: version2, - }, - { - name: "When downgrade version, then result contains error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: "experimental", - Version: version3, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantErrContains: versionUpgradeErr, - }, - } - - executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, - moduleToInstall) -} - -func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromVersionToChannel(t *testing.T) { - moduleToInstall := testutils.NewTestModule("module1", "new_channel") - availableModuleTemplates := (&ModuleTemplateListBuilder{}). - Add(moduleToInstall.Name, "regular", version1). - Add(moduleToInstall.Name, "new_channel", version2). - Add(moduleToInstall.Name, "fast", version3). - Add(moduleToInstall.Name, string(shared.NoneChannel), version1). - Add(moduleToInstall.Name, string(shared.NoneChannel), version2). - Add(moduleToInstall.Name, string(shared.NoneChannel), version3). - Build() - - availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - - tests := getRegularTemplatesTestCases{ - { - name: "When staying with the same version, then result contains no error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: string(shared.NoneChannel), - Version: version2, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantChannel: "new_channel", - wantVersion: version2, - }, - { - name: "When upgrade version, then result contains no error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: string(shared.NoneChannel), - Version: version1, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantChannel: "new_channel", - wantVersion: version2, - }, - { - name: "When downgrade version, then result contains error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(moduleToInstall). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: moduleToInstall.Name, - Channel: string(shared.NoneChannel), - Version: version3, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - wantErrContains: versionUpgradeErr, - }, - } - - executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, - moduleToInstall) -} - -func TestNewTemplateLookup_GetRegularTemplates_WhenModuleTemplateContainsInvalidDescriptor(t *testing.T) { - testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) - tests := []struct { - name string - kyma *v1beta2.Kyma - mrmExists bool - want templatelookup.ModuleTemplatesByModuleName - }{ - { - name: "When module enabled in Spec, then return ModuleTemplatesByModuleName with error, " + - "without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule).Build(), - mrmExists: false, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: provider.ErrDecode, - }, - }, - }, - { - name: "When module exits in ModuleStatus only, then return ModuleTemplatesByModuleName with error," + - "without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: testModule.Channel, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - mrmExists: false, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: provider.ErrDecode, - }, - }, - }, - { - name: "When module enabled in Spec, then return ModuleTemplatesByModuleName with error," + - "with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule).Build(), - mrmExists: true, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: provider.ErrDecode, - }, - }, - }, - { - name: "When module exits in ModuleStatus only, then return ModuleTemplatesByModuleName with error," + - "with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: testModule.Channel, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - mrmExists: true, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: provider.ErrDecode, - }, - }, - }, - } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - givenTemplateList := &v1beta2.ModuleTemplateList{} - moduleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - for _, module := range templatelookup.FetchModuleInfo(testCase.kyma) { - givenTemplateList.Items = append(givenTemplateList.Items, *builder.NewModuleTemplateBuilder(). - WithName(fmt.Sprintf("%s-%s", module.Name, testModule.Version)). - WithModuleName(module.Name). - WithChannel(module.Channel). - WithDescriptor(nil). - WithRawDescriptor([]byte("{invalid_json}")).Build()) - - if testCase.mrmExists { - moduleReleaseMetas.Items = append(moduleReleaseMetas.Items, - *builder.NewModuleReleaseMetaBuilder(). - WithModuleName(module.Name). - WithModuleChannelAndVersions([]v1beta2.ChannelVersionAssignment{ - {Channel: module.Channel, Version: testModule.Version}, - }).Build()) - } - } - reader := NewFakeModuleTemplateReader(*givenTemplateList, - moduleReleaseMetas) - lookup := templatelookup.NewTemplateLookup( - reader, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(reader), - moduletemplateinfolookup.NewByChannelStrategy(reader), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), - }, - ), - ) - got := lookup.GetRegularTemplates(t.Context(), testCase.kyma) - expected := len(testCase.want) - assert.Len(t, got, expected) - for key, module := range got { - wantModule, ok := testCase.want[key] - assert.True(t, ok) - assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) - require.ErrorIs(t, module.Err, wantModule.Err) - } - }) - } -} - -func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateNotFound(t *testing.T) { - testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) - - tests := []struct { - name string - kyma *v1beta2.Kyma - want templatelookup.ModuleTemplatesByModuleName - }{ - { - name: "When no module enabled in Spec, then return empty ModuleTemplatesByModuleName", - kyma: builder.NewKymaBuilder().Build(), - want: templatelookup.ModuleTemplatesByModuleName{}, - }, - { - name: "When module enabled in Spec, then return ModuleTemplatesByModuleName with error", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule).Build(), - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: common.ErrNoTemplatesInListResult, - }, - }, - }, - { - name: "When module exits in ModuleStatus only, then return ModuleTemplatesByModuleName with error", - kyma: builder.NewKymaBuilder(). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: testModule.Channel, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - }).Build(), - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: common.ErrNoTemplatesInListResult, - }, - }, - }, - } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - givenTemplateList := &v1beta2.ModuleTemplateList{} - reader := NewFakeModuleTemplateReader(*givenTemplateList, - v1beta2.ModuleReleaseMetaList{}) - lookup := templatelookup.NewTemplateLookup( - reader, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(reader), - moduletemplateinfolookup.NewByChannelStrategy(reader), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), - }, - ), - ) - got := lookup.GetRegularTemplates(t.Context(), testCase.kyma) - expected := len(testCase.want) - assert.Len(t, got, expected) - for key, module := range got { - wantModule, ok := testCase.want[key] - assert.True(t, ok) - assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) - require.ErrorIs(t, module.Err, wantModule.Err) - assert.Nil(t, module.ModuleTemplate) - } - }) - } -} - -func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateExists(t *testing.T) { - testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) - - tests := []struct { - name string - kyma *v1beta2.Kyma - mrmExist bool - want templatelookup.ModuleTemplatesByModuleName - }{ - { - name: "When module enabled in Spec, then return expected moduleTemplateInfo, without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule).Build(), - mrmExist: false, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithModuleName(testModule.Name). - WithChannel(testModule.Channel). - Build(), - }, - }, - }, - { - name: "When module enabled in Spec, then return expected moduleTemplateInfo, with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule).Build(), - mrmExist: true, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithModuleName(testModule.Name). - WithChannel(""). - Build(), - }, - }, - }, - { - name: "When module exits in ModuleStatus only, " + - "then return expected moduleTemplateInfo, without ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: testModule.Channel, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - Version: "1.0.0", - }).Build(), - mrmExist: false, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithModuleName(testModule.Name). - WithChannel(testModule.Channel). - Build(), - }, - }, - }, - { - name: "When module exits in ModuleStatus only, " + - "then return expected moduleTemplateInfo, with ModuleReleaseMeta", - kyma: builder.NewKymaBuilder(). - WithEnabledModule(testModule). - WithModuleStatus(v1beta2.ModuleStatus{ - Name: testModule.Name, - Channel: testModule.Channel, - Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMeta{ - Generation: 1, - }, - }, - Version: "1.0.0", - }).Build(), - mrmExist: true, - want: templatelookup.ModuleTemplatesByModuleName{ - testModule.Name: &templatelookup.ModuleTemplateInfo{ - DesiredChannel: testModule.Channel, - Err: nil, - ModuleTemplate: builder.NewModuleTemplateBuilder(). - WithModuleName(testModule.Name). - WithChannel(""). - Build(), - }, - }, - }, - } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - givenTemplateList := &v1beta2.ModuleTemplateList{} - moduleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - const moduleTemplateVersion = "1.0.0" - for _, module := range templatelookup.FetchModuleInfo(testCase.kyma) { - if testCase.mrmExist { - givenTemplateList.Items = append(givenTemplateList.Items, *builder.NewModuleTemplateBuilder(). - WithName(fmt.Sprintf("%s-%s", module.Name, moduleTemplateVersion)). - WithModuleName(module.Name). - WithVersion(moduleTemplateVersion). - WithOCM(compdescv2.SchemaVersion).Build()) - moduleReleaseMetas.Items = append(moduleReleaseMetas.Items, - *builder.NewModuleReleaseMetaBuilder(). - WithModuleName(module.Name). - WithModuleChannelAndVersions([]v1beta2.ChannelVersionAssignment{ - {Channel: module.Channel, Version: moduleTemplateVersion}, - }).Build()) - } else { - givenTemplateList.Items = append(givenTemplateList.Items, *builder.NewModuleTemplateBuilder(). - WithName(fmt.Sprintf("%s-%s", module.Name, moduleTemplateVersion)). - WithModuleName(module.Name). - WithAnnotation(shared.ModuleVersionAnnotation, moduleTemplateVersion). - WithChannel(module.Channel). - WithOCM(compdescv2.SchemaVersion).Build()) - } - } - reader := NewFakeModuleTemplateReader(*givenTemplateList, - moduleReleaseMetas) - lookup := templatelookup.NewTemplateLookup( - reader, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(reader), - moduletemplateinfolookup.NewByChannelStrategy(reader), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), - }, - ), - ) - expected := len(testCase.want) - got := lookup.GetRegularTemplates(t.Context(), testCase.kyma) - assert.Len(t, got, expected) - for key, module := range got { - wantModule, ok := testCase.want[key] - assert.True(t, ok) - assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) - require.ErrorIs(t, module.Err, wantModule.Err) - if !testCase.mrmExist { - assert.Equal(t, wantModule.Spec.Channel, module.Spec.Channel) - } - } - }) - } -} - -func TestTemplateNameMatch(t *testing.T) { - targetName := "module1" - - tests := []struct { - name string - template v1beta2.ModuleTemplate - want bool - }{ - { - name: "When moduleName is empty and no labels, Then return false", - template: v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - ModuleName: "", - }, - }, - want: false, - }, - { - name: "When moduleName is not equal to target name, Then return false", - template: v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - ModuleName: "module2", - }, - }, - want: false, - }, - { - name: "When moduleName is equal to target name, Then return true", - template: v1beta2.ModuleTemplate{ - Spec: v1beta2.ModuleTemplateSpec{ - ModuleName: "module1", - }, - }, - want: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := moduletemplateinfolookup.TemplateNameMatch(&tt.template, targetName); got != tt.want { - assert.Equal(t, tt.want, got) - } - }) - } -} - -type getRegularTemplatesTestCases []struct { - name string - kyma *v1beta2.Kyma - wantVersion string - wantChannel string - wantErrContains string -} - -func executeGetRegularTemplatesTestCases(t *testing.T, - testCases getRegularTemplatesTestCases, - availableModuleTemplates v1beta2.ModuleTemplateList, - availableModuleReleaseMetas v1beta2.ModuleReleaseMetaList, - moduleToInstall v1beta2.Module, -) { - t.Helper() - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - reader := NewFakeModuleTemplateReader(availableModuleTemplates, availableModuleReleaseMetas) - lookup := templatelookup.NewTemplateLookup( - reader, - provider.NewCachedDescriptorProvider(), - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(reader), - moduletemplateinfolookup.NewByChannelStrategy(reader), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), - }, - ), - ) - got := lookup.GetRegularTemplates(t.Context(), testCase.kyma) - assert.Len(t, got, 1) - for key, module := range got { - assert.Equal(t, key, moduleToInstall.Name) - if testCase.wantErrContains != "" { - assert.Contains(t, module.Err.Error(), testCase.wantErrContains) - } else { - assert.Equal(t, testCase.wantChannel, module.DesiredChannel) - assert.Equal(t, testCase.wantVersion, module.Spec.Version) - } - } - }) - } -} - -func generateModuleTemplateListWithModule(moduleName, moduleChannel, moduleVersion string) v1beta2.ModuleTemplateList { - templateList := v1beta2.ModuleTemplateList{} - templateList.Items = append(templateList.Items, *builder.NewModuleTemplateBuilder(). - WithName(fmt.Sprintf("%s-%s", moduleName, moduleVersion)). - WithModuleName(moduleName). - WithChannel(moduleChannel). - WithVersion(moduleVersion). - WithDescriptor(&types.Descriptor{ - ComponentDescriptor: &compdesc.ComponentDescriptor{ - Metadata: compdesc.Metadata{ - ConfiguredVersion: compdescv2.SchemaVersion, - }, - ComponentSpec: compdesc.ComponentSpec{ - ObjectMeta: ocmmetav1.ObjectMeta{ - Version: moduleVersion, - }, - }, - }, - }).Build()) - return templateList -} - -func generateModuleReleaseMetaList(moduleName string, - channelVersions []v1beta2.ChannelVersionAssignment, -) v1beta2.ModuleReleaseMetaList { - mrmList := v1beta2.ModuleReleaseMetaList{} - mrmList.Items = append(mrmList.Items, *builder.NewModuleReleaseMetaBuilder(). - WithModuleName(moduleName). - WithModuleChannelAndVersions(channelVersions). - Build()) - return mrmList -} - -type ModuleTemplateListBuilder struct { - ModuleTemplates []v1beta2.ModuleTemplate -} - -func (mtlb *ModuleTemplateListBuilder) Add(moduleName, moduleChannel, moduleVersion string) *ModuleTemplateListBuilder { - list := generateModuleTemplateListWithModule(moduleName, moduleChannel, moduleVersion) - mtlb.ModuleTemplates = append(mtlb.ModuleTemplates, list.Items...) - return mtlb -} - -func (mtlb *ModuleTemplateListBuilder) Build() v1beta2.ModuleTemplateList { - return v1beta2.ModuleTemplateList{ - Items: mtlb.ModuleTemplates, - } -} - -func moduleToInstallByVersion(moduleName, moduleVersion string) v1beta2.Module { - return testutils.NewTestModuleWithChannelVersion(moduleName, "", moduleVersion) -} diff --git a/pkg/testutils/moduletemplate.go b/pkg/testutils/moduletemplate.go index 58e381c926..8e297fb43c 100644 --- a/pkg/testutils/moduletemplate.go +++ b/pkg/testutils/moduletemplate.go @@ -11,9 +11,8 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup/common" "github.com/kyma-project/lifecycle-manager/pkg/util" ) @@ -33,13 +32,6 @@ func GetModuleTemplate(ctx context.Context, module v1beta2.Module, kyma *v1beta2.Kyma, ) (*v1beta2.ModuleTemplate, error) { - moduleTemplateInfoLookupStrategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(clnt), - moduletemplateinfolookup.NewByChannelStrategy(clnt), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(clnt), - }, - ) availableModule := templatelookup.ModuleInfo{ Module: module, } @@ -49,7 +41,8 @@ func GetModuleTemplate(ctx context.Context, return nil, fmt.Errorf("failed to get ModuleReleaseMeta: %w", err) } - templateInfo := moduleTemplateInfoLookupStrategies.Lookup(ctx, &availableModule, kyma, moduleReleaseMeta) + // Use the lookupModuleTemplate function directly since it's now in the same package + templateInfo := templatelookup.LookupModuleTemplate(ctx, clnt, &availableModule, kyma, moduleReleaseMeta) if templateInfo.Err != nil { return nil, fmt.Errorf("get module template: %w", templateInfo.Err) diff --git a/tests/integration/controller/kcp/suite_test.go b/tests/integration/controller/kcp/suite_test.go index 153584f580..02ceb56b31 100644 --- a/tests/integration/controller/kcp/suite_test.go +++ b/tests/integration/controller/kcp/suite_test.go @@ -49,18 +49,18 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator" "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator/fromerror" "github.com/kyma-project/lifecycle-manager/internal/setup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/log" "github.com/kyma-project/lifecycle-manager/pkg/queue" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" "github.com/kyma-project/lifecycle-manager/tests/integration" testskrcontext "github.com/kyma-project/lifecycle-manager/tests/integration/commontestutils/skrcontextimpl" _ "ocm.software/ocm/api/ocm" - . "github.com/kyma-project/lifecycle-manager/pkg/testutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + . "github.com/kyma-project/lifecycle-manager/pkg/testutils" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -166,13 +166,7 @@ var _ = BeforeSuite(func() { Metrics: metrics.NewKymaMetrics(metrics.NewSharedMetrics()), RemoteCatalog: remote.NewRemoteCatalogFromKyma(kcpClient, testSkrContextFactory, flags.DefaultRemoteSyncNamespace), - TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(kcpClient), - moduletemplateinfolookup.NewByChannelStrategy(kcpClient), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(kcpClient), - })), + TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, nil), }).SetupWithManager(mgr, ctrlruntime.Options{}, kyma.SetupOptions{ListenerAddr: UseRandomPort}) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/kyma/helper_test.go b/tests/integration/controller/kyma/helper_test.go index c4c31f3721..bdc25c83bc 100644 --- a/tests/integration/controller/kyma/helper_test.go +++ b/tests/integration/controller/kyma/helper_test.go @@ -69,6 +69,18 @@ func DeleteModuleTemplates(ctx context.Context, kcpClient client.Client, kyma *v Eventually(DeleteCR, Timeout, Interval). WithContext(ctx). WithArguments(kcpClient, template).Should(Succeed()) + + // Also delete the corresponding ModuleReleaseMeta + moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithNamespace(ControlPlaneNamespace). + WithName(module.Name). + WithModuleName(module.Name). + WithSingleModuleChannelAndVersions(module.Channel, + module.Channel). // Use channel as version for integration tests + Build() + Eventually(DeleteCR, Timeout, Interval). + WithContext(ctx). + WithArguments(kcpClient, moduleReleaseMeta).Should(Succeed()) } } @@ -83,6 +95,19 @@ func DeployModuleTemplates(ctx context.Context, kcpClient client.Client, kyma *v Eventually(CreateCR, Timeout, Interval).WithContext(ctx). WithArguments(kcpClient, template). Should(Succeed()) + + // Create corresponding ModuleReleaseMeta for proper templatelookup behavior + moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithNamespace(ControlPlaneNamespace). + WithName(module.Name). + WithModuleName(module.Name). + WithSingleModuleChannelAndVersions(module.Channel, + module.Channel). // Use channel as version for integration tests + Build() + Eventually(CreateCR, Timeout, Interval).WithContext(ctx). + WithArguments(kcpClient, moduleReleaseMeta). + Should(Succeed()) + managedModule := NewTestModuleWithFixName(module.Name, module.Channel, "") Eventually(ModuleTemplateExists, Timeout, Interval). WithArguments(ctx, kcpClient, managedModule, kyma). @@ -95,6 +120,17 @@ func DeployMandatoryModuleTemplate(ctx context.Context, kcpClient client.Client) Eventually(CreateCR, Timeout, Interval). WithContext(ctx). WithArguments(kcpClient, mandatoryTemplate).Should(Succeed()) + + // Create corresponding ModuleReleaseMeta for mandatory module + mandatoryModuleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithNamespace(ControlPlaneNamespace). + WithName("mandatory-template-operator"). + WithModuleName("mandatory-template-operator"). + WithMandatory(mandatoryChannel). // Use channel as mandatory version + Build() + Eventually(CreateCR, Timeout, Interval). + WithContext(ctx). + WithArguments(kcpClient, mandatoryModuleReleaseMeta).Should(Succeed()) } func DeleteMandatoryModuleTemplate(ctx context.Context, kcpClient client.Client) { @@ -102,6 +138,17 @@ func DeleteMandatoryModuleTemplate(ctx context.Context, kcpClient client.Client) Eventually(DeleteCR, Timeout, Interval). WithContext(ctx). WithArguments(kcpClient, mandatoryTemplate).Should(Succeed()) + + // Also delete the corresponding ModuleReleaseMeta + mandatoryModuleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithNamespace(ControlPlaneNamespace). + WithName("mandatory-template-operator"). + WithModuleName("mandatory-template-operator"). + WithMandatory(mandatoryChannel). + Build() + Eventually(DeleteCR, Timeout, Interval). + WithContext(ctx). + WithArguments(kcpClient, mandatoryModuleReleaseMeta).Should(Succeed()) } func createModuleTemplateName(module v1beta2.Module) string { diff --git a/tests/integration/controller/kyma/suite_test.go b/tests/integration/controller/kyma/suite_test.go index 88a8a3fe8b..8f47ea3a0c 100644 --- a/tests/integration/controller/kyma/suite_test.go +++ b/tests/integration/controller/kyma/suite_test.go @@ -49,18 +49,18 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator" "github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator/fromerror" "github.com/kyma-project/lifecycle-manager/internal/setup" + "github.com/kyma-project/lifecycle-manager/internal/templatelookup" "github.com/kyma-project/lifecycle-manager/pkg/log" "github.com/kyma-project/lifecycle-manager/pkg/queue" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" - "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" "github.com/kyma-project/lifecycle-manager/tests/integration" testskrcontext "github.com/kyma-project/lifecycle-manager/tests/integration/commontestutils/skrcontextimpl" _ "ocm.software/ocm/api/ocm" - . "github.com/kyma-project/lifecycle-manager/pkg/testutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + . "github.com/kyma-project/lifecycle-manager/pkg/testutils" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -161,13 +161,7 @@ var _ = BeforeSuite(func() { flags.DefaultRemoteSyncNamespace), RemoteSyncNamespace: flags.DefaultRemoteSyncNamespace, Metrics: metrics.NewKymaMetrics(metrics.NewSharedMetrics()), - TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, - moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies( - []moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ - moduletemplateinfolookup.NewByVersionStrategy(kcpClient), - moduletemplateinfolookup.NewByChannelStrategy(kcpClient), - moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(kcpClient), - })), + TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, nil), }).SetupWithManager(mgr, ctrlruntime.Options{}, kyma.SetupOptions{ListenerAddr: randomPort}) Expect(err).ToNot(HaveOccurred()) diff --git a/unit-test-coverage-lifecycle-manager.yaml b/unit-test-coverage-lifecycle-manager.yaml index aaf59e29c7..5d3fa8114c 100644 --- a/unit-test-coverage-lifecycle-manager.yaml +++ b/unit-test-coverage-lifecycle-manager.yaml @@ -44,5 +44,4 @@ packages: internal/util/collections: 87 pkg/module/sync: 10 pkg/templatelookup: 87 - pkg/templatelookup/moduletemplateinfolookup: 98 pkg/watcher: 10