diff --git a/cmd/main.go b/cmd/main.go index d2b10cfada..c7cedc7d06 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -65,6 +65,7 @@ import ( "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" @@ -280,13 +281,18 @@ func scheduleMetricsCleanup(kymaMetrics *metrics.KymaMetrics, cleanupIntervalInM func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDescriptorProvider, skrContextFactory remote.SkrContextProvider, event event.Event, flagVar *flags.FlagVar, options ctrlruntime.Options, skrWebhookManager *watcher.SKRWebhookManifestManager, kymaMetrics *metrics.KymaMetrics, - setupLog logr.Logger, maintenanceWindow templatelookup.MaintenanceWindow, -) { + setupLog logr.Logger, _ *maintenancewindows.MaintenanceWindow) { options.RateLimiter = internal.RateLimiter(flagVar.FailureBaseDelay, flagVar.FailureMaxDelay, flagVar.RateLimiterFrequency, flagVar.RateLimiterBurst) options.CacheSyncTimeout = flagVar.CacheSyncTimeout options.MaxConcurrentReconciles = flagVar.MaxConcurrentKymaReconciles + moduleTemplateInfoLookupStrategy := moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(mgr.GetClient()), + moduletemplateinfolookup.NewByChannelStrategy(mgr.GetClient()), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(mgr.GetClient()), + }) + if err := (&kyma.Reconciler{ Client: mgr.GetClient(), SkrContextFactory: skrContextFactory, @@ -306,7 +312,7 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe Metrics: kymaMetrics, RemoteCatalog: remote.NewRemoteCatalogFromKyma(mgr.GetClient(), skrContextFactory, flagVar.RemoteSyncNamespace), - TemplateLookup: templatelookup.NewTemplateLookup(mgr.GetClient(), descriptorProvider, maintenanceWindow), + TemplateLookup: templatelookup.NewTemplateLookup(mgr.GetClient(), descriptorProvider, moduleTemplateInfoLookupStrategy), }).SetupWithManager( mgr, options, kyma.SetupOptions{ ListenerAddr: flagVar.KymaListenerAddr, diff --git a/pkg/module/sync/runner.go b/pkg/module/sync/runner.go index db2106f900..4c4bbccb78 100644 --- a/pkg/module/sync/runner.go +++ b/pkg/module/sync/runner.go @@ -21,6 +21,7 @@ import ( "github.com/kyma-project/lifecycle-manager/pkg/log" "github.com/kyma-project/lifecycle-manager/pkg/module/common" "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" "github.com/kyma-project/lifecycle-manager/pkg/util" ) @@ -275,7 +276,7 @@ func generateModuleStatus(module *common.Module, existStatus *v1beta2.ModuleStat newModuleStatus.Message = module.Template.Err.Error() return *newModuleStatus } - if errors.Is(module.Template.Err, templatelookup.ErrNoTemplatesInListResult) { + if errors.Is(module.Template.Err, moduletemplateinfolookup.ErrNoTemplatesInListResult) { return v1beta2.ModuleStatus{ Name: module.ModuleName, Channel: module.Template.DesiredChannel, diff --git a/pkg/templatelookup/moduletemplateinfolookup/aggregated.go b/pkg/templatelookup/moduletemplateinfolookup/aggregated.go new file mode 100644 index 0000000000..dcf76e0c47 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/aggregated.go @@ -0,0 +1,47 @@ +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 { + Lookup(ctx context.Context, + moduleInfo *templatelookup.ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, + ) templatelookup.ModuleTemplateInfo + IsResponsible(moduleInfo *templatelookup.ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, + ) bool +} + +type AggregatedModuleTemplateInfoLookupStrategy struct { + strategies []ModuleTemplateInfoLookupStrategy +} + +func NewAggregatedModuleTemplateInfoLookupStrategy(strategies []ModuleTemplateInfoLookupStrategy) AggregatedModuleTemplateInfoLookupStrategy { + return AggregatedModuleTemplateInfoLookupStrategy{strategies: strategies} +} + +func (s AggregatedModuleTemplateInfoLookupStrategy) Lookup(ctx context.Context, + moduleInfo *templatelookup.ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, +) templatelookup.ModuleTemplateInfo { + for _, strategy := range s.strategies { + if strategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) { + return strategy.Lookup(ctx, moduleInfo, kyma, moduleReleaseMeta) + } + } + + return templatelookup.ModuleTemplateInfo{ + Err: ErrNoResponsibleStrategy, + } +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/aggregated_test.go b/pkg/templatelookup/moduletemplateinfolookup/aggregated_test.go new file mode 100644 index 0000000000..65d735790e --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/aggregated_test.go @@ -0,0 +1,66 @@ +package moduletemplateinfolookup_test + +import ( + "context" + "testing" + + "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/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_AggregatedModuleTemplateInfoLookupStrategy_Lookup_CallsResponsibleStrategy(t *testing.T) { + nonResponsibleStrategy := newLookupStrategyStub(false) + responsibleStrategy := newLookupStrategyStub(true) + aggregatedStrategy := moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + &nonResponsibleStrategy, + &responsibleStrategy, + }) + + moduleTemplateInfo := aggregatedStrategy.Lookup(context.Background(), nil, nil, nil) + + assert.True(t, responsibleStrategy.called) + assert.False(t, nonResponsibleStrategy.called) + require.NoError(t, moduleTemplateInfo.Err) +} + +func Test_AggregatedModuleTemplateInfoLookupStrategy_Lookup_ReturnsFailureWhenNoStrategyResponsible(t *testing.T) { + nonResponsibleStrategy := newLookupStrategyStub(false) + aggregatedStrategy := moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + &nonResponsibleStrategy, + }) + + moduleTemplateInfo := aggregatedStrategy.Lookup(context.Background(), nil, nil, nil) + + assert.False(t, nonResponsibleStrategy.called) + 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, + moduleInfo *templatelookup.ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, +) templatelookup.ModuleTemplateInfo { + s.called = true + return templatelookup.ModuleTemplateInfo{} +} + +func (s *LookupStrategyStub) IsResponsible(moduleInfo *templatelookup.ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, +) bool { + return s.responsible +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_channel.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel.go new file mode 100644 index 0000000000..1461811d6d --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_channel.go @@ -0,0 +1,138 @@ +package moduletemplateinfolookup + +import ( + "context" + "errors" + "fmt" + + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/pkg/log" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +var ( + ErrNotDefaultChannelAllowed = errors.New("specifying no default channel is not allowed") +) + +type ByChannelStrategy struct { + client client.Reader +} + +func NewByChannelStrategy(client client.Reader) ByChannelStrategy { + return ByChannelStrategy{client: client} +} + +func (ByChannelStrategy) IsResponsible(moduleInfo *templatelookup.ModuleInfo, + _ *v1beta2.Kyma, + 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 (p ByChannelStrategy) filterTemplatesByChannel(ctx context.Context, name, desiredChannel string) ( + *v1beta2.ModuleTemplate, error, +) { + templateList := &v1beta2.ModuleTemplateList{} + err := p.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 ", + ErrNoTemplatesInListResult, name, desiredChannel) + } + + if filteredTemplates[0].Spec.Mandatory { + return nil, fmt.Errorf("%w: for module %s in channel %s", + ErrTemplateMarkedAsMandatory, 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_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_test.go new file mode 100644 index 0000000000..febc89790c --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_channel_test.go @@ -0,0 +1,71 @@ +package moduletemplateinfolookup_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "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 kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) + + responsible := byChannelStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.True(t, responsible) +} + +func Test_ByChannelStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithChannel("regular").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = builder.NewModuleReleaseMetaBuilder().Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) + + responsible := byChannelStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.False(t, responsible) +} + +func Test_ByChannelStrategy_IsResponsible_ReturnsFalse_WhenInstalledByVersion(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) + + responsible := byChannelStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.False(t, responsible) +} + +func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + var kyma *v1beta2.Kyma = builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-regular"). + WithModuleName("test-module"). + WithVersion(""). + WithChannel("regular"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(nil, moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Equal(t, moduleTemplate.Name, moduleTemplateInfo.ModuleTemplate.Name) + assert.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.ModuleTemplate.Spec.ModuleName) + assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) + assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta.go new file mode 100644 index 0000000000..e94792341f --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta.go @@ -0,0 +1,52 @@ +package moduletemplateinfolookup + +import ( + "context" + + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ByModuleReleaseMetaStrategy struct { + client client.Reader +} + +func NewByModuleReleaseMetaStrategy(client client.Reader) ByModuleReleaseMetaStrategy { + return ByModuleReleaseMetaStrategy{client: client} +} + +func (ByModuleReleaseMetaStrategy) IsResponsible(moduleInfo *templatelookup.ModuleInfo, + _ *v1beta2.Kyma, + 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) + 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_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_test.go new file mode 100644 index 0000000000..b777c505ba --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_test.go @@ -0,0 +1,124 @@ +package moduletemplateinfolookup_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + 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() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = builder.NewModuleReleaseMetaBuilder().Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil) + + responsible := byMRMStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.True(t, responsible) +} + +func Test_ByModuleReleaseMetaStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithVersion("regular").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil) + + responsible := byMRMStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.False(t, responsible) +} + +func Test_ByModuleReleaseMeta_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + var kyma *v1beta2.Kyma = builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.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"). + WithChannel("none"). + Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byMRMStrategy.Lookup(nil, moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Equal(t, moduleTemplate.Name, moduleTemplateInfo.ModuleTemplate.Name) + assert.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.ModuleTemplate.Spec.ModuleName) + assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) + assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) +} + +func fakeClient(mts *v1beta2.ModuleTemplateList) client.Client { + scheme := machineryruntime.NewScheme() + machineryutilruntime.Must(api.AddToScheme(scheme)) + + return fake.NewClientBuilder().WithScheme(scheme).WithLists(mts).Build() +} + +// func fakeClient(mts *v1beta2.ModuleTemplateList) client.Client { +// scheme := machineryruntime.NewScheme() +// machineryutilruntime.Must(api.AddToScheme(scheme)) + +// return fake.NewClientBuilder().WithScheme(scheme).WithLists(mts).Build() +// } + +// 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.Module.Name = name +// return b +// } + +// func (b moduleInfoBuilder) WithVersion(version string) moduleInfoBuilder { +// b.moduleInfo.Module.Version = version +// return b +// } + +// func (b moduleInfoBuilder) WithChannel(channel string) moduleInfoBuilder { +// b.moduleInfo.Module.Channel = channel +// return b +// } + +// func (b moduleInfoBuilder) Enabled() moduleInfoBuilder { +// b.moduleInfo.Enabled = true +// return b +// } + +// func (b moduleInfoBuilder) Build() *templatelookup.ModuleInfo { +// return b.moduleInfo +// } diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version.go b/pkg/templatelookup/moduletemplateinfolookup/by_version.go new file mode 100644 index 0000000000..d08979af35 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_version.go @@ -0,0 +1,83 @@ +package moduletemplateinfolookup + +import ( + "context" + "fmt" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ByVersionStrategy struct { + client client.Reader +} + +func NewByVersionStrategy(client client.Reader) ByVersionStrategy { + return ByVersionStrategy{client: client} +} + +func (ByVersionStrategy) IsResponsible(moduleInfo *templatelookup.ModuleInfo, + _ *v1beta2.Kyma, + 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 (p ByVersionStrategy) filterTemplatesByVersion(ctx context.Context, name, version string) ( + *v1beta2.ModuleTemplate, error, +) { + templateList := &v1beta2.ModuleTemplateList{} + err := p.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", + ErrNoTemplatesInListResult, name, version) + } + if filteredTemplates[0].Spec.Mandatory { + return nil, fmt.Errorf("%w: for module %s in version %s", + ErrTemplateMarkedAsMandatory, name, version) + } + return filteredTemplates[0], nil +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_test.go new file mode 100644 index 0000000000..34666e2138 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_version_test.go @@ -0,0 +1,108 @@ +package moduletemplateinfolookup_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "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 kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) + + responsible := byVersionStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.True(t, responsible) +} + +func Test_ByVersionStrategy_IsResponsible_ReturnsFalse_WhenModuleReleaseMetaIsNotNil(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = builder.NewModuleReleaseMetaBuilder().Build() + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) + + responsible := byVersionStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.False(t, responsible) +} + +func Test_ByVersionStrategy_IsResponsible_ReturnsFalse_WhenNotInstalledByVersion(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithVersion("").WithChannel("regular").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) + + responsible := byVersionStrategy.IsResponsible(moduleInfo, kyma, moduleReleaseMeta) + + assert.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(nil, moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Equal(t, moduleTemplate.Name, moduleTemplateInfo.ModuleTemplate.Name) + assert.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.ModuleTemplate.Spec.ModuleName) + assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) + assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) +} + +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.Module.Name = name + return b +} + +func (b moduleInfoBuilder) WithVersion(version string) moduleInfoBuilder { + b.moduleInfo.Module.Version = version + return b +} + +func (b moduleInfoBuilder) WithChannel(channel string) moduleInfoBuilder { + b.moduleInfo.Module.Channel = channel + return b +} + +func (b moduleInfoBuilder) Enabled() moduleInfoBuilder { + b.moduleInfo.Enabled = true + return b +} + +func (b moduleInfoBuilder) Build() *templatelookup.ModuleInfo { + return b.moduleInfo +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/common.go b/pkg/templatelookup/moduletemplateinfolookup/common.go new file mode 100644 index 0000000000..d555623de5 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/common.go @@ -0,0 +1,58 @@ +package moduletemplateinfolookup + +import ( + "context" + "errors" + "fmt" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var ( + ErrNoTemplatesInListResult = errors.New("no templates were found") + ErrTemplateMarkedAsMandatory = errors.New("template marked as mandatory") + ErrTemplateNotIdentified = errors.New("no unique template could be identified") +) + +func TemplateNameMatch(template *v1beta2.ModuleTemplate, name string) bool { + if len(template.Spec.ModuleName) > 0 { + return template.Spec.ModuleName == name + } + + // Drop the legacyCondition once the label 'shared.ModuleName' is removed: https://github.com/kyma-project/lifecycle-manager/issues/1796 + if template.Labels == nil { + return false + } + return template.Labels[shared.ModuleName] == name +} + +func newMoreThanOneTemplateCandidateErr(moduleName string, + candidateTemplates []v1beta2.ModuleTemplate, +) error { + candidates := make([]string, len(candidateTemplates)) + for i, candidate := range candidateTemplates { + candidates[i] = candidate.GetName() + } + + return fmt.Errorf("%w: more than one module template found for module: %s, candidates: %v", + 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/regular.go b/pkg/templatelookup/regular.go index f617215507..67c4993a71 100644 --- a/pkg/templatelookup/regular.go +++ b/pkg/templatelookup/regular.go @@ -9,27 +9,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" - "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/remote" - "github.com/kyma-project/lifecycle-manager/pkg/log" ) var ( - ErrTemplateNotIdentified = errors.New("no unique template could be identified") - ErrNotDefaultChannelAllowed = errors.New("specifying no default channel is not allowed") - ErrNoTemplatesInListResult = errors.New("no templates were found") - ErrTemplateMarkedAsMandatory = errors.New("template marked as mandatory") - 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") ) -type MaintenanceWindow interface { - IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool - IsActive(kyma *v1beta2.Kyma) (bool, error) -} - type ModuleTemplateInfo struct { *v1beta2.ModuleTemplate Err error @@ -37,57 +26,70 @@ type ModuleTemplateInfo struct { DesiredChannel string } +type ModuleTemplateInfoLookupStrategy interface { + Lookup(ctx context.Context, + moduleInfo *ModuleInfo, + kyma *v1beta2.Kyma, + moduleReleaseMeta *v1beta2.ModuleReleaseMeta, + ) ModuleTemplateInfo +} + func NewTemplateLookup(reader client.Reader, descriptorProvider *provider.CachedDescriptorProvider, - maintenanceWindow MaintenanceWindow, + moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy, + ) *TemplateLookup { return &TemplateLookup{ - Reader: reader, - descriptorProvider: descriptorProvider, - maintenanceWindow: maintenanceWindow, + Reader: reader, + descriptorProvider: descriptorProvider, + moduleTemplateInfoLookupStrategy: moduleTemplateInfoLookupStrategy, } } type TemplateLookup struct { client.Reader - descriptorProvider *provider.CachedDescriptorProvider - maintenanceWindow MaintenanceWindow + descriptorProvider *provider.CachedDescriptorProvider + moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy } type ModuleTemplatesByModuleName map[string]*ModuleTemplateInfo func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2.Kyma) ModuleTemplatesByModuleName { templates := make(ModuleTemplatesByModuleName) - for _, module := range FetchModuleInfo(kyma) { - _, found := templates[module.Name] + for _, moduleInfo := range FetchModuleInfo(kyma) { + _, found := templates[moduleInfo.Name] if found { continue } - if module.ValidationError != nil { - templates[module.Name] = &ModuleTemplateInfo{Err: module.ValidationError} + if moduleInfo.ValidationError != nil { + templates[moduleInfo.Name] = &ModuleTemplateInfo{Err: moduleInfo.ValidationError} continue } - moduleReleaseMeta, err := GetModuleReleaseMeta(ctx, t, module.Name, kyma.Namespace) + moduleReleaseMeta, err := GetModuleReleaseMeta(ctx, t, moduleInfo.Name, kyma.Namespace) if client.IgnoreNotFound(err) != nil { - templates[module.Name] = &ModuleTemplateInfo{Err: err} + templates[moduleInfo.Name] = &ModuleTemplateInfo{Err: err} continue } - templateInfo := t.PopulateModuleTemplateInfo(ctx, module, kyma.Namespace, kyma.Spec.Channel, moduleReleaseMeta) + templateInfo := t.moduleTemplateInfoLookupStrategy.Lookup(ctx, + &moduleInfo, + kyma, + moduleReleaseMeta) + templateInfo = ValidateTemplateMode(templateInfo, kyma, moduleReleaseMeta) if templateInfo.Err != nil { - templates[module.Name] = &templateInfo + templates[moduleInfo.Name] = &templateInfo continue } if err := t.descriptorProvider.Add(templateInfo.ModuleTemplate); err != nil { templateInfo.Err = fmt.Errorf("failed to get descriptor: %w", err) - templates[module.Name] = &templateInfo + templates[moduleInfo.Name] = &templateInfo continue } for i := range kyma.Status.Modules { moduleStatus := &kyma.Status.Modules[i] - if moduleMatch(moduleStatus, module.Name) { + if moduleMatch(moduleStatus, moduleInfo.Name) { descriptor, err := t.descriptorProvider.GetDescriptor(templateInfo.ModuleTemplate) if err != nil { msg := "could not handle channel skew as descriptor from template cannot be fetched" @@ -97,56 +99,11 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2. markInvalidSkewUpdate(ctx, &templateInfo, moduleStatus, descriptor.Version) } } - templates[module.Name] = &templateInfo + templates[moduleInfo.Name] = &templateInfo } return templates } -func (t *TemplateLookup) PopulateModuleTemplateInfo(ctx context.Context, - module ModuleInfo, namespace, kymaChannel string, moduleReleaseMeta *v1beta2.ModuleReleaseMeta, -) ModuleTemplateInfo { - if moduleReleaseMeta == nil { - return t.populateModuleTemplateInfoWithoutModuleReleaseMeta(ctx, module, kymaChannel) - } - - return t.populateModuleTemplateInfoUsingModuleReleaseMeta(ctx, module, moduleReleaseMeta, kymaChannel, namespace) -} - -func (t *TemplateLookup) populateModuleTemplateInfoWithoutModuleReleaseMeta(ctx context.Context, - module ModuleInfo, kymaChannel string, -) ModuleTemplateInfo { - var templateInfo ModuleTemplateInfo - if module.IsInstalledByVersion() { - templateInfo = t.GetAndValidateByVersion(ctx, module.Name, module.Version) - } else { - templateInfo = t.GetAndValidateByChannel(ctx, module.Name, module.Channel, kymaChannel) - } - return templateInfo -} - -func (t *TemplateLookup) populateModuleTemplateInfoUsingModuleReleaseMeta(ctx context.Context, - module ModuleInfo, - moduleReleaseMeta *v1beta2.ModuleReleaseMeta, kymaChannel, namespace string, -) ModuleTemplateInfo { - var templateInfo ModuleTemplateInfo - templateInfo.DesiredChannel = getDesiredChannel(module.Channel, kymaChannel) - desiredModuleVersion, err := GetChannelVersionForModule(moduleReleaseMeta, templateInfo.DesiredChannel) - if err != nil { - templateInfo.Err = err - return templateInfo - } - - template, err := t.getTemplateByVersion(ctx, module.Name, desiredModuleVersion, namespace) - if err != nil { - templateInfo.Err = err - return templateInfo - } - - templateInfo.ModuleTemplate = template - - return templateInfo -} - func ValidateTemplateMode(template ModuleTemplateInfo, kyma *v1beta2.Kyma, moduleReleaseMeta *v1beta2.ModuleReleaseMeta, @@ -184,83 +141,6 @@ func validateTemplateModeWithModuleReleaseMeta(template ModuleTemplateInfo, kyma return template } -func (t *TemplateLookup) getTemplateByVersion(ctx context.Context, - moduleName, moduleVersion, namespace string, -) (*v1beta2.ModuleTemplate, error) { - moduleTemplate := &v1beta2.ModuleTemplate{} - - moduleTemplateName := fmt.Sprintf("%s-%s", moduleName, moduleVersion) - if err := t.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) GetAndValidateByChannel(ctx context.Context, - name, channel, defaultChannel string, -) ModuleTemplateInfo { - desiredChannel := getDesiredChannel(channel, defaultChannel) - info := ModuleTemplateInfo{ - DesiredChannel: desiredChannel, - } - - template, err := t.filterTemplatesByChannel(ctx, 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", - name, ErrNotDefaultChannelAllowed, - ) - return info - } - - logUsedChannel(ctx, name, actualChannel, defaultChannel) - info.ModuleTemplate = template - return info -} - -func (t *TemplateLookup) GetAndValidateByVersion(ctx context.Context, name, version string) ModuleTemplateInfo { - info := ModuleTemplateInfo{ - DesiredChannel: string(shared.NoneChannel), - } - template, err := t.filterTemplatesByVersion(ctx, name, version) - if err != nil { - info.Err = err - return info - } - - info.ModuleTemplate = template - return info -} - -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, - ), - ) - } -} - func moduleMatch(moduleStatus *v1beta2.ModuleStatus, moduleName string) bool { return moduleStatus.Name == moduleName } @@ -328,107 +208,3 @@ func filterVersion(version *semver.Version) *semver.Version { version.Major(), version.Minor(), version.Patch())) return filteredVersion } - -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 (t *TemplateLookup) filterTemplatesByChannel(ctx context.Context, name, desiredChannel string) ( - *v1beta2.ModuleTemplate, error, -) { - templateList := &v1beta2.ModuleTemplateList{} - err := t.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 ", - ErrNoTemplatesInListResult, name, desiredChannel) - } - - if filteredTemplates[0].Spec.Mandatory { - return nil, fmt.Errorf("%w: for module %s in channel %s", - ErrTemplateMarkedAsMandatory, name, desiredChannel) - } - - return filteredTemplates[0], nil -} - -func (t *TemplateLookup) filterTemplatesByVersion(ctx context.Context, name, version string) ( - *v1beta2.ModuleTemplate, error, -) { - templateList := &v1beta2.ModuleTemplateList{} - err := t.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", - ErrNoTemplatesInListResult, name, version) - } - if filteredTemplates[0].Spec.Mandatory { - return nil, fmt.Errorf("%w: for module %s in version %s", - ErrTemplateMarkedAsMandatory, name, version) - } - return filteredTemplates[0], nil -} - -func TemplateNameMatch(template *v1beta2.ModuleTemplate, name string) bool { - if len(template.Spec.ModuleName) > 0 { - return template.Spec.ModuleName == name - } - - // Drop the legacyCondition once the label 'shared.ModuleName' is removed: https://github.com/kyma-project/lifecycle-manager/issues/1796 - if template.Labels == nil { - return false - } - return template.Labels[shared.ModuleName] == name -} - -func NewMoreThanOneTemplateCandidateErr(moduleName string, - candidateTemplates []v1beta2.ModuleTemplate, -) error { - candidates := make([]string, len(candidateTemplates)) - for i, candidate := range candidateTemplates { - candidates[i] = candidate.GetName() - } - - return fmt.Errorf("%w: more than one module template found for module: %s, candidates: %v", - ErrTemplateNotIdentified, moduleName, candidates) -} diff --git a/pkg/templatelookup/regular_test.go b/pkg/templatelookup/regular_test.go index 98a9175309..442de6aa81 100644 --- a/pkg/templatelookup/regular_test.go +++ b/pkg/templatelookup/regular_test.go @@ -21,6 +21,7 @@ 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/pkg/templatelookup" + "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" ) @@ -332,7 +333,11 @@ func Test_GetRegularTemplates_WhenInvalidModuleProvided(t *testing.T) { for _, tt := range tests { test := tt t.Run(tt.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(nil, provider.NewCachedDescriptorProvider(), maintenanceWindowStub{}) + lookup := templatelookup.NewTemplateLookup(nil, provider.NewCachedDescriptorProvider(), moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(nil), + moduletemplateinfolookup.NewByChannelStrategy(nil), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil), + })) kyma := &v1beta2.Kyma{ Spec: test.KymaSpec, Status: test.KymaStatus, @@ -464,10 +469,14 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchModuleChannel(t *testing.T for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(testCase.availableModuleTemplate, - testCase.availableModuleReleaseMeta), + reader := NewFakeModuleTemplateReader(testCase.availableModuleTemplate, testCase.availableModuleReleaseMeta) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Equal(t, len(got), len(testCase.want)) for key, module := range got { @@ -538,10 +547,14 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchBetweenModuleVersions(t *t for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), + reader := NewFakeModuleTemplateReader(availableModuleTemplates, availableModuleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Len(t, got, 1) for key, module := range got { @@ -631,10 +644,15 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromChannelToVersion(t *te for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), + reader := NewFakeModuleTemplateReader(availableModuleTemplates, + availableModuleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Len(t, got, 1) for key, module := range got { @@ -724,10 +742,15 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromVersionToChannel(t *te for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), + reader := NewFakeModuleTemplateReader(availableModuleTemplates, + availableModuleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Len(t, got, 1) for key, module := range got { @@ -838,10 +861,15 @@ func TestNewTemplateLookup_GetRegularTemplates_WhenModuleTemplateContainsInvalid }).Build()) } } - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList, - moduleReleaseMetas), + reader := NewFakeModuleTemplateReader(*givenTemplateList, + moduleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Equal(t, len(got), len(testCase.want)) for key, module := range got { @@ -874,7 +902,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateNotFound(t *testin want: templatelookup.ModuleTemplatesByModuleName{ testModule.Name: &templatelookup.ModuleTemplateInfo{ DesiredChannel: testModule.Channel, - Err: templatelookup.ErrNoTemplatesInListResult, + Err: moduletemplateinfolookup.ErrNoTemplatesInListResult, }, }, }, @@ -893,7 +921,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateNotFound(t *testin want: templatelookup.ModuleTemplatesByModuleName{ testModule.Name: &templatelookup.ModuleTemplateInfo{ DesiredChannel: testModule.Channel, - Err: templatelookup.ErrNoTemplatesInListResult, + Err: moduletemplateinfolookup.ErrNoTemplatesInListResult, }, }, }, @@ -901,10 +929,15 @@ func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateNotFound(t *testin for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { givenTemplateList := &v1beta2.ModuleTemplateList{} - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList, - v1beta2.ModuleReleaseMetaList{}), + reader := NewFakeModuleTemplateReader(*givenTemplateList, + v1beta2.ModuleReleaseMetaList{}) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Equal(t, len(got), len(testCase.want)) for key, module := range got { @@ -1039,10 +1072,15 @@ func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateExists(t *testing. WithOCM(compdescv2.SchemaVersion).Build()) } } - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList, - moduleReleaseMetas), + reader := NewFakeModuleTemplateReader(*givenTemplateList, + moduleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(reader), + moduletemplateinfolookup.NewByChannelStrategy(reader), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(reader), + })) got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) assert.Equal(t, len(got), len(testCase.want)) for key, module := range got { @@ -1139,7 +1177,7 @@ func TestTemplateNameMatch(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := templatelookup.TemplateNameMatch(&tt.template, targetName); got != tt.want { + if got := moduletemplateinfolookup.TemplateNameMatch(&tt.template, targetName); got != tt.want { assert.Equal(t, tt.want, got) } }) @@ -1199,13 +1237,3 @@ func (mtlb *ModuleTemplateListBuilder) Build() v1beta2.ModuleTemplateList { func moduleToInstallByVersion(moduleName, moduleVersion string) v1beta2.Module { return testutils.NewTestModuleWithChannelVersion(moduleName, "", moduleVersion) } - -type maintenanceWindowStub struct{} - -func (m maintenanceWindowStub) IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool { - return false -} - -func (m maintenanceWindowStub) IsActive(kyma *v1beta2.Kyma) (bool, error) { - return false, nil -} diff --git a/pkg/testutils/moduletemplate.go b/pkg/testutils/moduletemplate.go index 707dcb8a07..f5e3209948 100644 --- a/pkg/testutils/moduletemplate.go +++ b/pkg/testutils/moduletemplate.go @@ -12,6 +12,7 @@ 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" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" "github.com/kyma-project/lifecycle-manager/pkg/util" ) @@ -29,23 +30,23 @@ func CreateModuleTemplate(ctx context.Context, func GetModuleTemplate(ctx context.Context, clnt client.Client, module v1beta2.Module, - defaultChannel string, - namespace string, + kyma *v1beta2.Kyma, ) (*v1beta2.ModuleTemplate, error) { - descriptorProvider := provider.NewCachedDescriptorProvider() - // replace maintenancePolicyHandlerStub with proper implementation for tests - templateLookup := templatelookup.NewTemplateLookup(clnt, descriptorProvider, maintenanceWindowStub{}) + moduleTemplateInfoLookupStrategy := moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(clnt), + moduletemplateinfolookup.NewByChannelStrategy(clnt), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(clnt), + }) availableModule := templatelookup.ModuleInfo{ Module: module, } - moduleReleaseMeta, err := GetModuleReleaseMeta(ctx, module.Name, namespace, clnt) + moduleReleaseMeta, err := GetModuleReleaseMeta(ctx, module.Name, kyma.Namespace, clnt) if !meta.IsNoMatchError(err) && client.IgnoreNotFound(err) != nil { return nil, fmt.Errorf("failed to get ModuleReleaseMeta: %w", err) } - templateInfo := templateLookup.PopulateModuleTemplateInfo(ctx, availableModule, namespace, - defaultChannel, moduleReleaseMeta) + templateInfo := moduleTemplateInfoLookupStrategy.Lookup(ctx, &availableModule, kyma, moduleReleaseMeta) if templateInfo.Err != nil { return nil, fmt.Errorf("get module template: %w", templateInfo.Err) @@ -56,11 +57,10 @@ func GetModuleTemplate(ctx context.Context, func ModuleTemplateExists(ctx context.Context, clnt client.Client, module v1beta2.Module, - defaultChannel string, - namespace string, + kyma *v1beta2.Kyma, ) error { - moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, defaultChannel, namespace) - if moduleTemplate == nil || errors.Is(err, templatelookup.ErrNoTemplatesInListResult) { + moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kyma) + if moduleTemplate == nil || errors.Is(err, moduletemplateinfolookup.ErrNoTemplatesInListResult) { return ErrNotFound } @@ -85,7 +85,7 @@ func ModuleTemplateExistsByName(ctx context.Context, func AllModuleTemplatesExists(ctx context.Context, clnt client.Client, kyma *v1beta2.Kyma) error { for _, module := range kyma.Spec.Modules { - if err := ModuleTemplateExists(ctx, clnt, module, kyma.Spec.Channel, kyma.Namespace); err != nil { + if err := ModuleTemplateExists(ctx, clnt, module, kyma); err != nil { return err } } @@ -97,11 +97,10 @@ func UpdateModuleTemplateSpec(ctx context.Context, clnt client.Client, module v1beta2.Module, key, - newValue, - kymaChannel string, - namespace string, + newValue string, + kyma *v1beta2.Kyma, ) error { - moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kymaChannel, namespace) + moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kyma) if err != nil { return err } @@ -141,9 +140,11 @@ func MandatoryModuleTemplateHasExpectedLabel(ctx context.Context, clnt client.Cl } func DeleteModuleTemplate(ctx context.Context, - clnt client.Client, module v1beta2.Module, kymaChannel string, namespace string, + clnt client.Client, + module v1beta2.Module, + kyma *v1beta2.Kyma, ) error { - moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kymaChannel, namespace) + moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kyma) if util.IsNotFound(err) { return nil } @@ -155,10 +156,12 @@ func DeleteModuleTemplate(ctx context.Context, return nil } -func ReadModuleVersionFromModuleTemplate(ctx context.Context, clnt client.Client, module v1beta2.Module, - channel string, namespace string, +func ReadModuleVersionFromModuleTemplate(ctx context.Context, + clnt client.Client, + module v1beta2.Module, + kyma *v1beta2.Kyma, ) (string, error) { - moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, channel, namespace) + moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kyma) if err != nil { return "", fmt.Errorf("failed to fetch ModuleTemplate: %w", err) } @@ -171,13 +174,3 @@ func ReadModuleVersionFromModuleTemplate(ctx context.Context, clnt client.Client return ocmDesc.Version, nil } - -type maintenanceWindowStub struct{} - -func (m maintenanceWindowStub) IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool { - return false -} - -func (m maintenanceWindowStub) IsActive(kyma *v1beta2.Kyma) (bool, error) { - return false, nil -} diff --git a/tests/e2e/module_deletion_test.go b/tests/e2e/module_deletion_test.go index 663b1ebab9..164ad807b1 100644 --- a/tests/e2e/module_deletion_test.go +++ b/tests/e2e/module_deletion_test.go @@ -279,7 +279,7 @@ var _ = Describe("Non Blocking Kyma Module Deletion", Ordered, func() { It("Then ModuleTemplate is no longer in SKR Cluster", func() { Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, kyma.Spec.Channel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Equal(ErrNotFound)) }) }) diff --git a/tests/e2e/module_upgrade_new_version_test.go b/tests/e2e/module_upgrade_new_version_test.go index 525ae06263..edf1aaa8da 100644 --- a/tests/e2e/module_upgrade_new_version_test.go +++ b/tests/e2e/module_upgrade_new_version_test.go @@ -79,7 +79,7 @@ var _ = Describe("Module Upgrade By New Version", Ordered, func() { By("And Kyma Module Version in Kyma Status is updated") newModuleTemplateVersion, err := ReadModuleVersionFromModuleTemplate(ctx, kcpClient, module, - kyma.Spec.Channel, ControlPlaneNamespace) + kyma) Expect(err).ToNot(HaveOccurred()) Eventually(ModuleVersionInKymaStatusIsCorrect). diff --git a/tests/e2e/modulereleasemeta_maintenance_window_module_downtime_test.go b/tests/e2e/modulereleasemeta_maintenance_window_module_downtime_test.go index c6e8972959..5df61ed8eb 100644 --- a/tests/e2e/modulereleasemeta_maintenance_window_module_downtime_test.go +++ b/tests/e2e/modulereleasemeta_maintenance_window_module_downtime_test.go @@ -119,7 +119,7 @@ var _ = Describe("Maintenance Window With ModuleReleaseMeta and Module Downtime" By("And Kyma Module Version in Kyma Status is updated") newModuleTemplateVersion, err := ReadModuleVersionFromModuleTemplate(ctx, kcpClient, module, - kyma.Spec.Channel, ControlPlaneNamespace) + kyma) Expect(err).ToNot(HaveOccurred()) Eventually(ModuleVersionInKymaStatusIsCorrect). diff --git a/tests/e2e/modulereleasemeta_module_upgrade_new_version_test.go b/tests/e2e/modulereleasemeta_module_upgrade_new_version_test.go index fc81f3f0a0..3613f52dba 100644 --- a/tests/e2e/modulereleasemeta_module_upgrade_new_version_test.go +++ b/tests/e2e/modulereleasemeta_module_upgrade_new_version_test.go @@ -79,7 +79,7 @@ var _ = Describe("Module with ModuleReleaseMeta Upgrade By New Version", Ordered By("And Kyma Module Version in Kyma Status is updated") newModuleTemplateVersion, err := ReadModuleVersionFromModuleTemplate(ctx, kcpClient, module, - kyma.Spec.Channel, ControlPlaneNamespace) + kyma) Expect(err).ToNot(HaveOccurred()) Eventually(ModuleVersionInKymaStatusIsCorrect). diff --git a/tests/e2e/modulereleasemeta_not_allowed_installation_test.go b/tests/e2e/modulereleasemeta_not_allowed_installation_test.go index dda391ca4f..af5ea1ba3f 100644 --- a/tests/e2e/modulereleasemeta_not_allowed_installation_test.go +++ b/tests/e2e/modulereleasemeta_not_allowed_installation_test.go @@ -20,7 +20,7 @@ var _ = Describe("ModuleReleaseMeta Not Allowed Installation", Ordered, func() { By("The the ModuleTemplate exists in the KCP Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, module, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Succeed()) By("And the ModuleReleaseMeta exists on the KCP Cluster") diff --git a/tests/e2e/modulereleasemeta_sync_test.go b/tests/e2e/modulereleasemeta_sync_test.go index b7bb9d3f25..9a1be65a5c 100644 --- a/tests/e2e/modulereleasemeta_sync_test.go +++ b/tests/e2e/modulereleasemeta_sync_test.go @@ -24,7 +24,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("Then the Template Operator v1 ModuleTemplate exists in the KCP Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, module, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Succeed()) Eventually(ImmediatelyRequeueKyma). @@ -35,7 +35,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And the Template Operator v1 ModuleTemplate exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Succeed()) By("And the ModuleReleaseMeta exists on the KCP Cluster with the correct channel-version") @@ -80,7 +80,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And the Template Operator v1 ModuleTemplate no longer exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Equal(ErrNotFound)) }) @@ -99,7 +99,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And the Template Operator v1 ModuleTemplate exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Succeed()) }) @@ -122,7 +122,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And the Template Operator v1 ModuleTemplate no longer exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Equal(ErrNotFound)) }) @@ -141,7 +141,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And the Template Operator v1 ModuleTemplate exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Succeed()) }) @@ -154,13 +154,13 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("Then Template Operator v1 ModuleTemplate no longer exists on the KCP Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, module, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Equal(ErrNotFound)) By("Then Template Operator v1 ModuleTemplate no longer exists on the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Equal(ErrNotFound)) }) @@ -178,13 +178,13 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("Then the Template Operator v2 ModuleTemplate exists in the KCP Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, module, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Succeed()) By("And the Template Operator v2 ModuleTemplate exists in the SKR Cluster") Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, v1beta2.DefaultChannel, RemoteNamespace). + WithArguments(skrClient, module, kyma). Should(Succeed()) By("And the ModuleReleaseMeta exists on the KCP Cluster with the correct channel-version") diff --git a/tests/integration/controller/kcp/helper_test.go b/tests/integration/controller/kcp/helper_test.go index 5088a62103..57e4457a25 100644 --- a/tests/integration/controller/kcp/helper_test.go +++ b/tests/integration/controller/kcp/helper_test.go @@ -111,10 +111,9 @@ func watcherLabelsAnnotationsExist(clnt client.Client, remoteKyma *v1beta2.Kyma, func expectModuleTemplateSpecGetReset( clnt client.Client, module v1beta2.Module, - kymaChannel string, - namespace string, + kyma *v1beta2.Kyma, ) error { - moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kymaChannel, namespace) + moduleTemplate, err := GetModuleTemplate(ctx, clnt, module, kyma) if err != nil { return err } diff --git a/tests/integration/controller/kcp/remote_sync_test.go b/tests/integration/controller/kcp/remote_sync_test.go index edb0a79ff0..510ed5de8f 100644 --- a/tests/integration/controller/kcp/remote_sync_test.go +++ b/tests/integration/controller/kcp/remote_sync_test.go @@ -103,11 +103,11 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { It("ModuleTemplates should be synchronized in both clusters", func() { By("ModuleTemplate exists in KCP cluster") Eventually(ModuleTemplateExists, Timeout, Interval). - WithArguments(ctx, kcpClient, moduleInKCP, kyma.Spec.Channel, ControlPlaneNamespace). + WithArguments(ctx, kcpClient, moduleInKCP, kyma). Should(Succeed()) By("ModuleTemplate exists in SKR cluster") - Eventually(ModuleTemplateExists, Timeout, Interval).WithArguments(ctx, skrClient, moduleInKCP, - kyma.Spec.Channel, RemoteNamespace).Should(Succeed()) + Eventually(ModuleTemplateExists, Timeout, Interval). + WithArguments(ctx, skrClient, moduleInKCP, kyma).Should(Succeed()) By("No module synced to remote Kyma") Eventually(NotContainsModuleInSpec, Timeout, Interval). @@ -117,7 +117,7 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { By("Remote Module Catalog created") Eventually(ModuleTemplateExists, Timeout, Interval). - WithArguments(ctx, skrClient, moduleInSKR, kyma.Spec.Channel, RemoteNamespace). + WithArguments(ctx, skrClient, moduleInSKR, kyma). Should(Succeed()) Eventually(containsModuleTemplateCondition, Timeout, Interval). WithArguments(skrClient, skrKyma.GetName(), flags.DefaultRemoteSyncNamespace). @@ -181,13 +181,12 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { By("Update SKR Module Template spec.data.spec field") Eventually(UpdateModuleTemplateSpec, Timeout, Interval). WithContext(ctx). - WithArguments(skrClient, moduleInSKR, InitSpecKey, "valueUpdated", kyma.Spec.Channel, RemoteNamespace). + WithArguments(skrClient, moduleInSKR, InitSpecKey, "valueUpdated", kyma). Should(Succeed()) By("Expect SKR Module Template spec.data.spec field get reset") Eventually(expectModuleTemplateSpecGetReset, 2*Timeout, Interval). - WithArguments(skrClient, - moduleInSKR, kyma.Spec.Channel, RemoteNamespace). + WithArguments(skrClient, moduleInSKR, kyma). Should(Succeed()) }) diff --git a/tests/integration/controller/kcp/suite_test.go b/tests/integration/controller/kcp/suite_test.go index 784209be82..5a0b4b0c45 100644 --- a/tests/integration/controller/kcp/suite_test.go +++ b/tests/integration/controller/kcp/suite_test.go @@ -42,13 +42,13 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/crd" "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" "github.com/kyma-project/lifecycle-manager/internal/event" - "github.com/kyma-project/lifecycle-manager/internal/maintenancewindows" "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" "github.com/kyma-project/lifecycle-manager/internal/remote" "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/pkg/testutils" "github.com/kyma-project/lifecycle-manager/tests/integration" testskrcontext "github.com/kyma-project/lifecycle-manager/tests/integration/commontestutils/skrcontextimpl" @@ -143,7 +143,6 @@ var _ = BeforeSuite(func() { testSkrContextFactory = testskrcontext.NewDualClusterFactory(kcpClient.Scheme(), testEventRec) descriptorProvider = provider.NewCachedDescriptorProvider() crdCache = crd.NewCache(nil) - maintenanceWindow, _ := maintenancewindows.InitializeMaintenanceWindow(logr, "/not-required", "not-required") err = (&kyma.Reconciler{ Client: kcpClient, SkrContextFactory: testSkrContextFactory, @@ -156,7 +155,11 @@ var _ = BeforeSuite(func() { IsManagedKyma: true, Metrics: metrics.NewKymaMetrics(metrics.NewSharedMetrics()), RemoteCatalog: remote.NewRemoteCatalogFromKyma(kcpClient, testSkrContextFactory, flags.DefaultRemoteSyncNamespace), - TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, maintenanceWindow), + TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(kcpClient), + moduletemplateinfolookup.NewByChannelStrategy(kcpClient), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(kcpClient), + })), }).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 3606ddb2cf..f2ed775f37 100644 --- a/tests/integration/controller/kyma/helper_test.go +++ b/tests/integration/controller/kyma/helper_test.go @@ -86,7 +86,7 @@ func DeployModuleTemplates(ctx context.Context, kcpClient client.Client, kyma *v Should(Succeed()) managedModule := NewTestModuleWithFixName(module.Name, module.Channel, "") Eventually(ModuleTemplateExists, Timeout, Interval). - WithArguments(ctx, kcpClient, managedModule, module.Channel, ControlPlaneNamespace). + WithArguments(ctx, kcpClient, managedModule, kyma). Should(Succeed()) } } diff --git a/tests/integration/controller/kyma/kyma_test.go b/tests/integration/controller/kyma/kyma_test.go index 35fc20c719..ed728b0c8b 100644 --- a/tests/integration/controller/kyma/kyma_test.go +++ b/tests/integration/controller/kyma/kyma_test.go @@ -162,8 +162,7 @@ var _ = Describe("Kyma enable one Module", Ordered, func() { if len(modulesStatus) != 1 { return ErrWrongModulesStatus } - template, err := GetModuleTemplate(ctx, kcpClient, module, v1beta2.DefaultChannel, - ControlPlaneNamespace) + template, err := GetModuleTemplate(ctx, kcpClient, module, createdKyma) if err != nil { return err } @@ -518,7 +517,7 @@ func updateKCPModuleTemplateSpecData(kymaName, valueUpdated string) func() error } for _, activeModule := range createdKyma.Spec.Modules { return UpdateModuleTemplateSpec(ctx, kcpClient, - activeModule, InitSpecKey, valueUpdated, createdKyma.Spec.Channel, ControlPlaneNamespace) + activeModule, InitSpecKey, valueUpdated, createdKyma) } return nil } diff --git a/tests/integration/controller/kyma/manifest_test.go b/tests/integration/controller/kyma/manifest_test.go index d6e12d1799..0f89f87e43 100644 --- a/tests/integration/controller/kyma/manifest_test.go +++ b/tests/integration/controller/kyma/manifest_test.go @@ -127,7 +127,7 @@ var _ = Describe("Manifest.Spec is rendered correctly", Ordered, func() { RegisterDefaultLifecycleForKyma(kyma) It("validate Manifest", func() { - moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma.Spec.Channel, ControlPlaneNamespace) + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma) Expect(err).NotTo(HaveOccurred()) expectManifest := expectManifestFor(kyma) @@ -197,7 +197,7 @@ var _ = Describe("Manifest.Spec is reset after manual update", Ordered, func() { }) It("validate Manifest", func() { - moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma.Spec.Channel, ControlPlaneNamespace) + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma) Expect(err).NotTo(HaveOccurred()) expectManifest := expectManifestFor(kyma) @@ -266,8 +266,8 @@ var _ = Describe("Update Module Template Version", Ordered, func() { { newVersionAndLayerDigest := updateModuleTemplateVersion updatedVersionAndLayerDigest := validateModuleTemplateVersionUpdated - updateModuleTemplateWith := funWrap(updateKCPModuleTemplate(module, kyma.Spec.Channel)) - validateModuleTemplateWith := funWrap(validateKCPModuleTemplate(module, kyma.Spec.Channel)) + updateModuleTemplateWith := funWrap(updateKCPModuleTemplate(module, kyma)) + validateModuleTemplateWith := funWrap(validateKCPModuleTemplate(module, kyma)) updateModuleTemplateVersionAndLayerDigest := updateModuleTemplateWith(newVersionAndLayerDigest) validateVersionAndLayerDigestAreUpdated := validateModuleTemplateWith(updatedVersionAndLayerDigest) @@ -333,11 +333,10 @@ var _ = Describe("Modules can only be referenced via module name", Ordered, func It("returns the expected operator", func() { Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, moduleReferencedWithLabel, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, moduleReferencedWithLabel, kyma). Should(Succeed()) - moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, moduleReferencedWithLabel, v1beta2.DefaultChannel, - ControlPlaneNamespace) + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, moduleReferencedWithLabel, kyma) Expect(err).ToNot(HaveOccurred()) foundModuleName := moduleTemplate.Labels[shared.ModuleName] Expect(foundModuleName).To(Equal(moduleReferencedWithLabel.Name)) @@ -348,8 +347,7 @@ var _ = Describe("Modules can only be referenced via module name", Ordered, func It("cannot find the operator", func() { Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, moduleReferencedWithNamespacedName, v1beta2.DefaultChannel, - ControlPlaneNamespace). + WithArguments(kcpClient, moduleReferencedWithNamespacedName, kyma). Should(Equal(ErrNotFound)) }) }) @@ -358,7 +356,7 @@ var _ = Describe("Modules can only be referenced via module name", Ordered, func It("cannot find the operator", func() { Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(kcpClient, moduleReferencedWithFQDN, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, moduleReferencedWithFQDN, kyma). Should(Equal(ErrNotFound)) }) }) @@ -506,9 +504,9 @@ func validateManifestSpecResource(manifestResource, moduleTemplateData *unstruct } // getKCPModuleTemplate is a generic ModuleTemplate validation function. -func validateKCPModuleTemplate(module v1beta2.Module, kymaChannel string) func(moduleTemplateFn) error { +func validateKCPModuleTemplate(module v1beta2.Module, kyma *v1beta2.Kyma) func(moduleTemplateFn) error { return func(validateFunc moduleTemplateFn) error { - moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kymaChannel, ControlPlaneNamespace) + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma) if err != nil { return err } @@ -523,9 +521,9 @@ func validateKCPModuleTemplate(module v1beta2.Module, kymaChannel string) func(m } // updateKCPModuleTemplate is a generic ModuleTemplate update function. -func updateKCPModuleTemplate(module v1beta2.Module, kymaChannel string) func(moduleTemplateFn) error { +func updateKCPModuleTemplate(module v1beta2.Module, kyma *v1beta2.Kyma) func(moduleTemplateFn) error { return func(updateFunc moduleTemplateFn) error { - moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kymaChannel, ControlPlaneNamespace) + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, module, kyma) if err != nil { return err } diff --git a/tests/integration/controller/kyma/suite_test.go b/tests/integration/controller/kyma/suite_test.go index 0e43ca2a3f..3c457eb97b 100644 --- a/tests/integration/controller/kyma/suite_test.go +++ b/tests/integration/controller/kyma/suite_test.go @@ -41,13 +41,13 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/controller/kyma" "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" "github.com/kyma-project/lifecycle-manager/internal/event" - "github.com/kyma-project/lifecycle-manager/internal/maintenancewindows" "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" "github.com/kyma-project/lifecycle-manager/internal/remote" "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" @@ -137,7 +137,6 @@ var _ = BeforeSuite(func() { kcpClient = mgr.GetClient() testEventRec := event.NewRecorderWrapper(mgr.GetEventRecorderFor(shared.OperatorName)) testSkrContextFactory := testskrcontext.NewSingleClusterFactory(kcpClient, mgr.GetConfig(), testEventRec) - maintenanceWindow, _ := maintenancewindows.InitializeMaintenanceWindow(logr, "/not-required", "/not-required") err = (&kyma.Reconciler{ Client: kcpClient, Event: testEventRec, @@ -148,7 +147,11 @@ var _ = BeforeSuite(func() { InKCPMode: false, RemoteSyncNamespace: flags.DefaultRemoteSyncNamespace, Metrics: metrics.NewKymaMetrics(metrics.NewSharedMetrics()), - TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, maintenanceWindow), + TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, moduletemplateinfolookup.NewAggregatedModuleTemplateInfoLookupStrategy([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(kcpClient), + moduletemplateinfolookup.NewByChannelStrategy(kcpClient), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(kcpClient), + })), }).SetupWithManager(mgr, ctrlruntime.Options{ RateLimiter: internal.RateLimiter( 1*time.Second, 5*time.Second,