diff --git a/api/go.mod b/api/go.mod index ac067f7907..a52bcdadb2 100644 --- a/api/go.mod +++ b/api/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/stretchr/testify v1.10.0 k8s.io/apimachinery v0.32.1 - sigs.k8s.io/controller-runtime v0.19.4 + sigs.k8s.io/controller-runtime v0.20.0 ) require github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -26,7 +26,6 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -35,8 +34,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/x448/float16 v0.8.4 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.28.0 // indirect @@ -46,9 +43,8 @@ require ( google.golang.org/protobuf v1.35.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.2 // indirect - k8s.io/apiextensions-apiserver v0.31.2 // indirect - k8s.io/client-go v0.31.2 // indirect + k8s.io/api v0.32.0 // indirect + k8s.io/client-go v0.32.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect diff --git a/api/go.sum b/api/go.sum index f0e07a63fb..003a89bd25 100644 --- a/api/go.sum +++ b/api/go.sum @@ -38,8 +38,6 @@ github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgY github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -87,8 +85,6 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -136,22 +132,22 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= -k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0= -k8s.io/apiextensions-apiserver v0.31.2/go.mod h1:i+Geh+nGCJEGiCGR3MlBDkS7koHIIKWVfWeRFiOsUcM= +k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= +k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= +k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= +k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= +k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.4 h1:SUmheabttt0nx8uJtoII4oIP27BVVvAKFvdvGFwV/Qo= -sigs.k8s.io/controller-runtime v0.19.4/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= +sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs= +sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= diff --git a/api/v1beta2/modulereleasemeta_types.go b/api/v1beta2/modulereleasemeta_types.go index a7828a7317..78917aa05a 100644 --- a/api/v1beta2/modulereleasemeta_types.go +++ b/api/v1beta2/modulereleasemeta_types.go @@ -33,12 +33,14 @@ type ModuleReleaseMetaSpec struct { Channels []ChannelVersionAssignment `json:"channels"` // Beta indicates if the module is in beta state. Beta modules are only available for beta Kymas. + // +optional // +kubebuilder:default:=false - Beta bool `json:"beta,omitempty"` + Beta bool `json:"beta"` // Internal indicates if the module is internal. Internal modules are only available for internal Kymas. + // +optional // +kubebuilder:default:=false - Internal bool `json:"internal,omitempty"` + Internal bool `json:"internal"` } // +kubebuilder:object:root=true diff --git a/api/v1beta2/moduletemplate_types.go b/api/v1beta2/moduletemplate_types.go index 2fc4b1360d..9c758ce316 100644 --- a/api/v1beta2/moduletemplate_types.go +++ b/api/v1beta2/moduletemplate_types.go @@ -223,39 +223,27 @@ func (m *ModuleTemplate) IsInternal() bool { return false } -var ErrInvalidVersion = errors.New("can't find valid semantic version") - -// getVersionLegacy() returns the version of the ModuleTemplate from the annotation on the object. -// Remove once shared.ModuleVersionAnnotation is removed. -func (m *ModuleTemplate) getVersionLegacy() (string, error) { - if m.Annotations != nil { - moduleVersion, found := m.Annotations[shared.ModuleVersionAnnotation] - if found { - return moduleVersion, nil - } +// https://github.com/kyma-project/lifecycle-manager/issues/2096 +// Refactor this function to drop the label fallback after the migration to the new ModuleTemplate format is completed. +func (m *ModuleTemplate) GetVersion() string { + version := m.Spec.Version + if version == "" { + version = m.Annotations[shared.ModuleVersionAnnotation] } - return "", ErrInvalidVersion + return version } -// GetVersion returns the declared version of the ModuleTemplate from it's Spec. -func (m *ModuleTemplate) GetVersion() (*semver.Version, error) { - var versionValue string - var err error - - if m.Spec.Version == "" { - versionValue, err = m.getVersionLegacy() - if err != nil { - return nil, err - } - } else { - versionValue = m.Spec.Version - } +var ErrInvalidVersion = errors.New("can't find valid semantic version") - version, err := semver.NewVersion(versionValue) +// GetSemanticVersion returns the declared version of the ModuleTemplate as semantic version. +func (m *ModuleTemplate) GetSemanticVersion() (*semver.Version, error) { + version := m.GetVersion() + + semanticVersion, err := semver.NewVersion(version) if err != nil { return nil, fmt.Errorf("%w: %s", ErrInvalidVersion, err.Error()) } - return version, nil + return semanticVersion, nil } // https://github.com/kyma-project/lifecycle-manager/issues/2096 @@ -279,3 +267,13 @@ func (m *ModuleTemplate) HasSyncDisabled() bool { } return false } + +// https://github.com/kyma-project/lifecycle-manager/issues/2096 +// Refactor this function to drop the label fallback after the migration to the new ModuleTemplate format is completed. +func (m *ModuleTemplate) GetModuleName() string { + moduleName := m.Spec.ModuleName + if moduleName == "" { + moduleName = m.Labels[shared.ModuleName] + } + return moduleName +} diff --git a/api/v1beta2/moduletemplate_types_test.go b/api/v1beta2/moduletemplate_types_test.go index b02b375e20..afaeafe7b9 100644 --- a/api/v1beta2/moduletemplate_types_test.go +++ b/api/v1beta2/moduletemplate_types_test.go @@ -4,13 +4,14 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" ) -func Test_GetVersion(t *testing.T) { +func Test_GetSemanticVersion(t *testing.T) { const testVersion = "1.0.1" const otherVersion = "0.0.1" tests := []struct { @@ -20,7 +21,7 @@ func Test_GetVersion(t *testing.T) { expectedErr string }{ { - name: "Test GetVersion() by annotation (legacy)", + name: "Test GetSemanticVersion() by annotation (legacy)", m: &v1beta2.ModuleTemplate{ ObjectMeta: apimetav1.ObjectMeta{ Annotations: map[string]string{ @@ -31,7 +32,7 @@ func Test_GetVersion(t *testing.T) { expectedVersion: testVersion, }, { - name: "Test GetVersion() by explicit version in Spec", + name: "Test GetSemanticVersion() by explicit version in Spec", m: &v1beta2.ModuleTemplate{ Spec: v1beta2.ModuleTemplateSpec{ Version: testVersion, @@ -40,7 +41,7 @@ func Test_GetVersion(t *testing.T) { expectedVersion: testVersion, }, { - name: "Test GetVersion() with both version in Spec and annotation", + name: "Test GetSemanticVersion() with both version in Spec and annotation", m: &v1beta2.ModuleTemplate{ ObjectMeta: apimetav1.ObjectMeta{ Annotations: map[string]string{ @@ -75,32 +76,140 @@ func Test_GetVersion(t *testing.T) { } for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { - actualVersion, err := testCase.m.GetVersion() + actualVersion, err := testCase.m.GetSemanticVersion() if err != nil { if actualVersion != nil { - t.Errorf("GetVersion(): Returned version should be nil when error is not nil") + t.Errorf("GetSemanticVersion(): Returned version should be nil when error is not nil") } if testCase.expectedErr == "" { - t.Errorf("GetVersion(): Unexpected error: %v", err) + t.Errorf("GetSemanticVersion(): Unexpected error: %v", err) } if !strings.Contains(err.Error(), testCase.expectedErr) { - t.Errorf("GetVersion(): Actual error = %v, expected error: %v", err, testCase.expectedErr) + t.Errorf("GetSemanticVersion(): Actual error = %v, expected error: %v", err, testCase.expectedErr) } return } if actualVersion == nil { - t.Errorf("GetVersion(): Returned version should not be nil when error is nil") + t.Errorf("GetSemanticVersion(): Returned version should not be nil when error is nil") } if testCase.expectedVersion == "" { - t.Errorf("GetVersion(): Expected version is empty but non-nil version is returned") + t.Errorf("GetSemanticVersion(): Expected version is empty but non-nil version is returned") } if actualVersion != nil && actualVersion.String() != testCase.expectedVersion { - t.Errorf("GetVersion(): actual version = %v, expected version: %v", actualVersion.String(), + t.Errorf("GetSemanticVersion(): actual version = %v, expected version: %v", actualVersion.String(), testCase.expectedVersion) } }) } } + +//nolint:dupl // similar but not duplicate +func Test_GetVersion(t *testing.T) { + tests := []struct { + name string + m *v1beta2.ModuleTemplate + expectedVersion string + }{ + { + name: "Test GetVersion() by annotation (legacy)", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Annotations: map[string]string{ + shared.ModuleVersionAnnotation: "1.0.0-annotated", + }, + }, + Spec: v1beta2.ModuleTemplateSpec{}, + }, + expectedVersion: "1.0.0-annotated", + }, + { + name: "Test GetVersion() by spec.version", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Annotations: map[string]string{}, + }, + Spec: v1beta2.ModuleTemplateSpec{ + Version: "2.0.0-spec", + }, + }, + expectedVersion: "2.0.0-spec", + }, + { + name: "Test GetVersion() spec.moduleName has priority over annotation", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Annotations: map[string]string{ + shared.ModuleVersionAnnotation: "1.0.0-annotated", + }, + }, + Spec: v1beta2.ModuleTemplateSpec{ + Version: "2.0.0-spec", + }, + }, + expectedVersion: "2.0.0-spec", + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + actualVersion := testCase.m.GetVersion() + assert.Equal(t, testCase.expectedVersion, actualVersion) + }) + } +} + +//nolint:dupl // similar but not duplicate +func Test_GetModuleName(t *testing.T) { + tests := []struct { + name string + m *v1beta2.ModuleTemplate + expectedName string + }{ + { + name: "Test GetModuleName() by label", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Labels: map[string]string{ + shared.ModuleName: "labelled-module", + }, + }, + Spec: v1beta2.ModuleTemplateSpec{}, + }, + expectedName: "labelled-module", + }, + { + name: "Test GetModuleName() by spec.moduleName", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Labels: map[string]string{}, + }, + Spec: v1beta2.ModuleTemplateSpec{ + ModuleName: "spec-module", + }, + }, + expectedName: "spec-module", + }, + { + name: "Test GetModuleName() spec.moduleName has priority over label", + m: &v1beta2.ModuleTemplate{ + ObjectMeta: apimetav1.ObjectMeta{ + Labels: map[string]string{ + shared.ModuleName: "labelled-module", + }, + }, + Spec: v1beta2.ModuleTemplateSpec{ + ModuleName: "spec-module", + }, + }, + expectedName: "spec-module", + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + actualName := testCase.m.GetModuleName() + assert.Equal(t, testCase.expectedName, actualName) + }) + } +} diff --git a/cmd/main.go b/cmd/main.go index d2b10cfada..f66ac2b3ad 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" @@ -116,7 +117,7 @@ func main() { } cacheOptions := internal.GetCacheOptions(flagVar.IsKymaManaged, flagVar.IstioNamespace, - flagVar.IstioGatewayNamespace, flagVar.RemoteSyncNamespace) + flagVar.IstioGatewayNamespace) setupManager(flagVar, cacheOptions, scheme, setupLog) } @@ -280,13 +281,19 @@ 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 + moduleTemplateInfoLookupStrategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies([]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 +313,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, moduleTemplateInfoLookupStrategies), }).SetupWithManager( mgr, options, kyma.SetupOptions{ ListenerAddr: flagVar.KymaListenerAddr, diff --git a/config/rbac/namespace_bindings/kustomization.yaml b/config/rbac/namespace_bindings/kustomization.yaml index d1b8329d73..8e9a9d4f54 100644 --- a/config/rbac/namespace_bindings/kustomization.yaml +++ b/config/rbac/namespace_bindings/kustomization.yaml @@ -13,6 +13,4 @@ resources: - role_binding.yaml # Comment the following to disable manifest integration - watcher_certmanager_role.yaml - - skr_role.yaml - watcher_certmanager_role_binding.yaml - - skr_role_binding.yaml diff --git a/config/rbac/namespace_bindings/skr_role.yaml b/config/rbac/namespace_bindings/skr_role.yaml deleted file mode 100644 index 27bdb53aa4..0000000000 --- a/config/rbac/namespace_bindings/skr_role.yaml +++ /dev/null @@ -1,43 +0,0 @@ ---- -# Give controller-manager permissions to the resources residing in kyma-system namespace on the SKR cluster -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: controller-manager-skr - namespace: kyma-system -rules: -- apiGroups: - - operator.kyma-project.io - resources: - - kymas - verbs: - - list - - watch - - delete - - get - - create - - patch - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/status - verbs: - - get - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - moduletemplates - verbs: - - list - - watch - - delete \ No newline at end of file diff --git a/config/rbac/namespace_bindings/skr_role_binding.yaml b/config/rbac/namespace_bindings/skr_role_binding.yaml deleted file mode 100644 index 2772232b08..0000000000 --- a/config/rbac/namespace_bindings/skr_role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: controller-manager-skr - namespace: kyma-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: controller-manager-skr -subjects: - - kind: ServiceAccount - name: controller-manager diff --git a/docs/contributor/04-local-test-setup.md b/docs/contributor/04-local-test-setup.md index 3df96bcc2c..718c447bb4 100644 --- a/docs/contributor/04-local-test-setup.md +++ b/docs/contributor/04-local-test-setup.md @@ -1,7 +1,4 @@ -# Local Test Setup in the Control Plane Mode Using k3d - -> ### Supported Versions -> For more information on the tooling versions expected in the project, see [`versions.yaml`](../../versions.yaml). +# Configure a Local Test Setup ## Context @@ -16,283 +13,162 @@ This setup is deployed with the following security features enabled: * Strict mTLS connection between Kyma Control Plane (KCP) and SKR clusters * SAN Pinning (SAN of client TLS certificate needs to match the DNS annotation of a corresponding Kyma CR) -## Procedure - -### KCP Cluster Setup - -1. Create a local KCP cluster: - - ```shell - k3d cluster create kcp-local --port 9443:443@loadbalancer \ - --registry-create k3d-registry.localhost:0.0.0.0:5111 \ - --k3s-arg '--disable=traefik@server:0' \ - --k3s-arg --tls-san=host.k3d.internal@server:* - ``` +## Prerequisites -2. Open `/etc/hosts` file on your local system: +Install the following tooling in the versions defined in [`versions.yaml`](../../versions.yaml): - ```shell - sudo nano /etc/hosts - ``` +- [Docker](https://www.docker.com/) +- [Go](https://go.dev/) +- [golangci-lint](https://golangci-lint.run/) +- [istioctl](https://istio.io/latest/docs/ops/diagnostic-tools/istioctl/) +- [k3d](https://k3d.io/stable/) +- [kubectl](https://kubernetes.io/docs/tasks/tools/) +- [kustomize](https://kustomize.io/) +- [modulectl](https://github.com/kyma-project/modulectl) +- [yq](https://github.com/mikefarah/yq/tree/master) - Add an entry for your local k3d registry created in step 1: +## Procedure - ```txt - 127.0.0.1 k3d-registry.localhost - ``` +Follow the steps using scripts from the project root. -3. Install the following prerequisites required by Lifecycle Manager: +### 1. Create Test Clusters - 1. Istio CRDs using `istioctl`: +Create local test clusters for SKR and KCP. - ```shell - brew install istioctl && \ - istioctl install --set profile=demo -y - ``` +```sh +K8S_VERSION=$(yq e '.k8s' ./versions.yaml) +CERT_MANAGER_VERSION=$(yq e '.certManager' ./versions.yaml) +./scripts/tests/create_test_clusters.sh --k8s-version $K8S_VERSION --cert-manager-version $CERT_MANAGER_VERSION +``` - 2. `cert-manager` by Jetstack: +### 2. Install the Custom Resource Definitions - ```shell - kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml - ``` +Install the [Lifecycle Manager CRDs](./resources/README.md) in the KCP cluster. -4. Deploy Lifecycle Manager in the cluster: +```sh +./scripts/tests/install_crds.sh +``` - ```shell - make local-deploy-with-watcher IMG=europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:latest - ``` +### 3. Deploy Lifecycle Manager - > **TIP:** If you get an error similar to the following, wait a couple of seconds and rerun the command. - > - > ```shell - > Error from server (InternalError): error when creating "STDIN": Internal error occurred: failed calling webhook "webhook.cert-manager.io": failed to call webhook: Post "https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s": no endpoints available for service "cert-manager-webhook" - > ``` +You can deploy Lifecycle Manager either from the registry or local sources. Choose one of the below options: -
- Custom Lifecycle Manager image deployment - If you want to test a custom image of Lifecycle Manager, run the following: +1. Deploy a built image from the registry, for example, the `latest` image from the `prod` registry. - ```shell - # build your local image - make docker-build IMG=k3d-registry.localhost:5111/: - # push the image to the local registry - make docker-push IMG=k3d-registry.localhost:5111/: - # deploy Lifecycle Manager using the image (note the change to port 5000 which is exposed in the cluster) - make local-deploy-with-watcher IMG=k3d-registry.localhost:5000/: - ``` -
+ ```sh + REGISTRY=prod + TAG=latest + ./scripts/tests/deploy_klm_from_registry.sh --image-registry $REGISTRY --image-tag $TAG + ``` -5. Create a ModuleTemplate CR using [modulectl](https://github.com/kyma-project/modulectl). - The ModuleTemplate CR includes component descriptors for module installations. +1. Build a new image from the local sources, push it to the local KCP registry, and deploy it. - In this tutorial, we will create a ModuleTemplate CR from the [`template-operator`](https://github.com/kyma-project/template-operator) repository. - Adjust the path to your `template-operator` local directory or any other reference module operator accordingly. - ```shell - cd - - # generate the manifests and save them to the template-operator.yaml file - make build-manifests - - # create the a ModuleTemplate CR and save it to the template.yaml file - modulectl create --config-file ./module-config.yaml --registry http://k3d-registry.localhost:5111 --insecure - ``` + ```sh + ./scripts/tests/deploy_klm_from_sources.sh + ``` -6. Verify images pushed to the local registry: +### 4. Deploy a Kyma CR - ```shell - curl http://k3d-registry.localhost:5111/v2/_catalog\?n\=100 - ``` +```sh +SKR_HOST=host.k3d.internal +./scripts/tests/deploy_kyma.sh $SKR_HOST +``` - The output should look like the following: +### 5. Verify If the Kyma CR Becomes Ready - ```shell - {"repositories":["component-descriptors/kyma-project.io/module/template-operator"]} - ``` +1. Verify if the Kyma CR is in the `Ready` state in KCP. It takes roughly 1–2 minutes. -7. Open the generated `template.yaml` file and change the following line: + ```sh + kubectl config use-context k3d-kcp + kubectl get kyma/kyma-sample -n kcp-system + ``` - ```yaml - <...> - - baseUrl: k3d-registry.localhost:5111 - <...> - ``` - To the following: +1. Verify if the Kyma CR is in the `Ready` state in SKR. It takes roughly 1-2 minutes. - ```yaml - <...> - - baseUrl: k3d-registry.localhost:5000 - <...> - ``` + ```sh + kubectl config use-context k3d-skr + kubectl get kyma/default -n kyma-system + ``` - You need the change because the operators are running inside of two local k3d clusters, and the internal port for the k3d registry is set by default to `5000`. +### 6. [OPTIONAL] Deploy the template-operator Module -8. Apply the template: +Build the template-operator module from the local sources, push it to the local KCP registry, and deploy it. - ```shell - kubectl apply -f ./template.yaml - ``` + ```sh + cd -### SKR Cluster Setup + make build-manifests + modulectl create --config-file ./module-config.yaml --registry http://localhost:5111 --insecure -Create a local Kyma runtime (SKR) cluster: + kubectl config use-context k3d-kcp + # repository URL is localhost:5111 on the host machine but must be k3d-kcp-registry.localhost:5000 within the cluster + yq e '.spec.descriptor.component.repositoryContexts[0].baseUrl = "k3d-kcp-registry.localhost:5000"' ./template.yaml | kubectl apply -f - -```shell -k3d cluster create skr-local --k3s-arg --tls-san=host.k3d.internal@server:* -``` + MT_VERSION=$(yq e '.spec.version' ./template.yaml) + cd + ./scripts/tests/deploy_modulereleasemeta.sh template-operator regular:$MT_VERSION + ``` -### Create a Kyma CR and a Remote Secret +### 7. [OPTIONAL] Add the template-operator Module to the Kyma CR and Verify If It Becomes Ready -1. Switch the context for using the KCP cluster: +1. Add the template-operator module to the Kyma CR spec. - ```shell - kubectl config use-context k3d-kcp-local + ```sh + kubectl config use-context k3d-skr + kubectl get kyma/default -n kyma-system -o yaml | yq e '.spec.modules[0]={"name": "template-operator"}' | kubectl apply -f - ``` -2. Generate and apply a sample Kyma CR and its corresponding Secret on KCP: - - ```shell - cat < - Running Lifecycle Manager on a local machine and not on a cluster - If you are running Lifecycle Manager on your local machine and not as a deployment on a cluster, use the following to create a Kyma CR and Secret: - - ```shell - cat << EOF | kubectl apply -f - - --- - apiVersion: v1 - kind: Secret - metadata: - name: kyma-sample - namespace: kcp-system - labels: - "operator.kyma-project.io/kyma-name": "kyma-sample" - "operator.kyma-project.io/managed-by": "lifecycle-manager" - data: - config: $(k3d kubeconfig get skr-local | base64 | tr -d '\n') - --- - apiVersion: operator.kyma-project.io/v1beta2 - kind: Kyma - metadata: - annotations: - skr-domain: "example.domain.com" - name: kyma-sample - namespace: kcp-system - spec: - channel: regular - modules: - - name: template-operator - EOF - ``` - - -### Watcher and Module Installation Verification - -Check the Kyma CR events to verify if the `SKRWebhookIsReady` condition is set to `True`. -Also make sure if the state of the `template-operator` is `Ready` and check the overall `state`. - -```yaml -status: - activeChannel: regular - conditions: - - lastTransitionTime: "2023-02-28T06:42:00Z" - message: skrwebhook is synchronized - observedGeneration: 1 - reason: SKRWebhookIsReady - status: "True" - type: Ready - lastOperation: - lastUpdateTime: "2023-02-28T06:42:00Z" - operation: kyma is ready - modules: - - channel: regular - fqdn: kyma-project.io/module/template-operator - manifest: - apiVersion: operator.kyma-project.io/v1beta2 - kind: Manifest - metadata: - generation: 1 - name: kyma-sample-template-operator-3685142144 - namespace: kcp-system - name: template-operator - state: Ready - template: - apiVersion: operator.kyma-project.io/v1beta2 - kind: ModuleTemplate - metadata: - generation: 1 - name: moduletemplate-template-operator - namespace: kcp-system - version: 1.2.3 - state: Ready -``` +1. Remove the module from the Kyma CR spec. -### (Optional) Check the Functionality of the Watcher Component + ```sh + kubectl config use-context k3d-skr + kubectl get kyma/default -n kyma-system -o yaml | yq e 'del(.spec.modules[0])' | kubectl apply -f - + ``` -1. Switch the context to use the SKR cluster: +### 8. [OPTIONAL] Verify Conditions - ```shell - kubectl config use-context k3d-skr-local - ``` +Check the conditions of the Kyma CR in the KCP cluster. -2. Change the channel of the `template-operator` module to trigger a watcher event to KCP: +- `SKRWebhook` to determine if the webhook has been installed to the SKR +- `ModuleCatalog` to determine if the ModuleTemplate CRs and ModuleReleaseMeta CRs haven been synced to the SKR cluster +- `Modules` to determine if the added modules are `Ready` - ```yaml - modules: - - name: template-operator - channel: fast - ``` +```sh +kubectl config use-context k3d-kcp +kubectl get kyma/kyma-sample -n kcp-system -o yaml | yq e '.status.conditions' +``` -### Verify logs +### 9. [OPTIONAL] Verify If Watcher Events Reach KCP -1. By watching the `skr-webhook` deployment logs, verify if the KCP request is sent successfully: +1. Flick the channel to trigger an event. - ```log - 1.6711877286771238e+09 INFO skr-webhook Kyma UPDATE validated from webhook - 1.6711879279507768e+09 INFO skr-webhook incoming admission review for: operator.kyma-project.io/v1alpha1, Kind=Kyma - 1.671187927950956e+09 INFO skr-webhook KCP {"url": "https://host.k3d.internal:9443/v1/lifecycle-manager/event"} - 1.6711879280545895e+09 INFO skr-webhook sent request to KCP successfully for resource default/kyma-sample - 1.6711879280546305e+09 INFO skr-webhook kcp request succeeded + ```sh + kubectl config use-context k3d-skr + kubectl get kyma/default -n kyma-system -o yaml | yq e '.spec.channel="regular"' | kubectl apply -f - + kubectl get kyma/default -n kyma-system -o yaml | yq e '.spec.channel="fast"' | kubectl apply -f - ``` -2. In Lifecycle Manager's logs, verify if the listener is logging messages indicating the reception of a message from the watcher: +1. Verify if Lifecycle Manger received the event in KCP. - ```log - {"level":"INFO","date":"2023-01-05T09:21:51.01093031Z","caller":"event/skr_events_listener.go:111","msg":"dispatched event object into channel","context":{"Module":"Listener","resource-name":"kyma-sample"}} - {"level":"INFO","date":"2023-01-05T09:21:51.010985Z","logger":"listener","caller":"controllers/setup.go:100","msg":"event coming from SKR, adding default/kyma-sample to queue","context":{}} - {"level":"INFO","date":"2023-01-05T09:21:51.011080512Z","caller":"controllers/kyma_controller.go:87","msg":"reconciling modules","context":{"controller":"kyma","controllerGroup":"operator.kyma-project.io","controllerKind":"Kyma","kyma":{"name":"kyma-sample","namespace":"default"},"namespace":"default","name":"kyma-sample","reconcileID":"f9b42382-dc68-41d2-96de-02b24e3ac2d6"}} - {"level":"INFO","date":"2023-01-05T09:21:51.043800866Z","caller":"controllers/kyma_controller.go:206","msg":"syncing state","context":{"controller":"kyma","controllerGroup":"operator.kyma-project.io","controllerKind":"Kyma","kyma":{"name":"kyma-sample","namespace":"default"},"namespace":"default","name":"kyma-sample","reconcileID":"f9b42382-dc68-41d2-96de-02b24e3ac2d6","state":"Processing"}} + ```sh + kubectl config use-context k3d-kcp + kubectl logs deploy/klm-controller-manager -n kcp-system | grep "event received from SKR" ``` -### Cleanup +### 10. [OPTIONAL] Delete the Local Test Clusters -Run the following command to remove the local testing clusters: +Remove the local SKR and KCP test clusters. ```shell -k3d cluster rm kcp-local skr-local +k3d cluster rm kcp skr ``` diff --git a/internal/cache_options.go b/internal/cache_options.go index cc7a64a017..0af1f02130 100644 --- a/internal/cache_options.go +++ b/internal/cache_options.go @@ -19,10 +19,9 @@ type DefaultCacheOptions struct { } type KcpCacheOptions struct { - CacheOptions cache.Options - istioNamespace string - kcpNamespace string - remoteNamespace string + CacheOptions cache.Options + istioNamespace string + kcpNamespace string } func (c *DefaultCacheOptions) GetCacheOptions() cache.Options { @@ -47,14 +46,12 @@ func (c *KcpCacheOptions) GetCacheOptions() cache.Options { }, &v1beta2.Kyma{}: { Namespaces: map[string]cache.Config{ - c.remoteNamespace: {}, - c.kcpNamespace: {}, + c.kcpNamespace: {}, }, }, &v1beta2.ModuleTemplate{}: { Namespaces: map[string]cache.Config{ - c.remoteNamespace: {}, - c.kcpNamespace: {}, + c.kcpNamespace: {}, }, }, &v1beta2.ModuleReleaseMeta{}: { @@ -88,12 +85,11 @@ func (c *KcpCacheOptions) GetCacheOptions() cache.Options { } } -func GetCacheOptions(isKymaManaged bool, istioNamespace, kcpNamespace, remoteNamespace string) cache.Options { +func GetCacheOptions(isKymaManaged bool, istioNamespace, kcpNamespace string) cache.Options { if isKymaManaged { options := &KcpCacheOptions{ - istioNamespace: istioNamespace, - kcpNamespace: kcpNamespace, - remoteNamespace: remoteNamespace, + istioNamespace: istioNamespace, + kcpNamespace: kcpNamespace, } return options.GetCacheOptions() } diff --git a/internal/descriptor/cache/key.go b/internal/descriptor/cache/key.go index f5d7cf90e2..4a6472f663 100644 --- a/internal/descriptor/cache/key.go +++ b/internal/descriptor/cache/key.go @@ -9,7 +9,7 @@ import ( type DescriptorKey string func GenerateDescriptorKey(template *v1beta2.ModuleTemplate) DescriptorKey { - version, err := template.GetVersion() + version, err := template.GetSemanticVersion() if err == nil { return DescriptorKey(fmt.Sprintf("%s:%s:%d:%s", template.Name, template.Spec.Channel, template.Generation, version)) diff --git a/internal/maintenancewindows/maintenance_window.go b/internal/maintenancewindows/maintenance_window.go index 2f1a5389f4..ce358ebdce 100644 --- a/internal/maintenancewindows/maintenance_window.go +++ b/internal/maintenancewindows/maintenance_window.go @@ -73,14 +73,13 @@ func (MaintenanceWindow) IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma } // module not installed yet => no need for maintenance window - moduleStatus := kyma.Status.GetModuleStatus(moduleTemplate.Spec.ModuleName) + moduleStatus := kyma.Status.GetModuleStatus(moduleTemplate.GetModuleName()) if moduleStatus == nil { return false } // module already installed in this version => no need for maintenance window - installedVersion := moduleStatus.Version - return installedVersion != moduleTemplate.Spec.Version + return moduleStatus.Version != moduleTemplate.GetVersion() } // IsActive determines if a maintenance window is currently active. 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/by_channel_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy.go new file mode 100644 index 0000000000..27293e9ada --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy.go @@ -0,0 +1,135 @@ +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" +) + +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 ", + 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_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go new file mode 100644 index 0000000000..1f04802ea6 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go @@ -0,0 +1,69 @@ +package moduletemplateinfolookup_test + +import ( + "context" + "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 moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(nil) + + responsible := byChannelStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) + + assert.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) + + assert.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) + + assert.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(). + WithName("test-module-regular"). + WithModuleName("test-module"). + WithVersion(""). + WithChannel("regular"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), 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_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy.go new file mode 100644 index 0000000000..579a5373c6 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy.go @@ -0,0 +1,52 @@ +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) + 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 new file mode 100644 index 0000000000..ba6f1469ee --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go @@ -0,0 +1,80 @@ +package moduletemplateinfolookup_test + +import ( + "context" + "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() + moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder().Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(nil) + + responsible := byMRMStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) + + assert.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) + + assert.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"). + WithChannel("none"). + Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byMRMStrategy.Lookup(context.Background(), 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() +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go new file mode 100644 index 0000000000..95bd6c3b62 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy.go @@ -0,0 +1,82 @@ +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" +) + +// 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", + 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_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go new file mode 100644 index 0000000000..243d0abd16 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go @@ -0,0 +1,106 @@ +package moduletemplateinfolookup_test + +import ( + "context" + "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 moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(nil) + + responsible := byVersionStrategy.IsResponsible(moduleInfo, moduleReleaseMeta) + + assert.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) + + assert.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) + + 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(context.Background(), 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..21f4d2a7c5 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/common.go @@ -0,0 +1,59 @@ +package moduletemplateinfolookup + +import ( + "context" + "errors" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" +) + +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/moduletemplateinfolookup/strategies.go b/pkg/templatelookup/moduletemplateinfolookup/strategies.go new file mode 100644 index 0000000000..441240b8fe --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/strategies.go @@ -0,0 +1,50 @@ +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 new file mode 100644 index 0000000000..8ca6399f6e --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/strategies_test.go @@ -0,0 +1,91 @@ +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(context.Background(), 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(context.Background(), 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(context.Background(), 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(context.Background(), 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/regular.go b/pkg/templatelookup/regular.go index f617215507..c13703c6ee 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,69 @@ 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 +98,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 +140,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 +207,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..5f55d33782 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.NewModuleTemplateInfoLookupStrategies([]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.NewModuleTemplateInfoLookupStrategies([]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 { @@ -494,13 +503,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchBetweenModuleVersions(t *t availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - tests := []struct { - name string - kyma *v1beta2.Kyma - wantVersion string - wantChannel string - wantErrContains string - }{ + tests := getRegularTemplatesTestCases{ { name: "When upgrade version, then result contains no error", kyma: builder.NewKymaBuilder(). @@ -536,25 +539,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchBetweenModuleVersions(t *t }, } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), - provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) - got := lookup.GetRegularTemplates(context.TODO(), 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.ModuleTemplate.Spec.Version) - } - } - }) - } + executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, moduleToInstall) } func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromChannelToVersion(t *testing.T) { @@ -570,13 +555,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromChannelToVersion(t *te availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - tests := []struct { - name string - kyma *v1beta2.Kyma - wantVersion string - wantChannel string - wantErrContains string - }{ + tests := getRegularTemplatesTestCases{ { name: "When staying with the same version, then result contains no error", kyma: builder.NewKymaBuilder(). @@ -629,25 +608,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromChannelToVersion(t *te }, } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), - provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) - got := lookup.GetRegularTemplates(context.TODO(), 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.ModuleTemplate.Spec.Version) - } - } - }) - } + executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, moduleToInstall) } func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromVersionToChannel(t *testing.T) { @@ -663,13 +624,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromVersionToChannel(t *te availableModuleReleaseMetas := v1beta2.ModuleReleaseMetaList{} - tests := []struct { - name string - kyma *v1beta2.Kyma - wantVersion string - wantChannel string - wantErrContains string - }{ + tests := getRegularTemplatesTestCases{ { name: "When staying with the same version, then result contains no error", kyma: builder.NewKymaBuilder(). @@ -722,25 +677,7 @@ func TestTemplateLookup_GetRegularTemplates_WhenSwitchFromVersionToChannel(t *te }, } - for _, testCase := range tests { - t.Run(testCase.name, func(t *testing.T) { - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(availableModuleTemplates, - availableModuleReleaseMetas), - provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) - got := lookup.GetRegularTemplates(context.TODO(), 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.ModuleTemplate.Spec.Version) - } - } - }) - } + executeGetRegularTemplatesTestCases(t, tests, availableModuleTemplates, availableModuleReleaseMetas, moduleToInstall) } func TestNewTemplateLookup_GetRegularTemplates_WhenModuleTemplateContainsInvalidDescriptor(t *testing.T) { @@ -838,10 +775,15 @@ func TestNewTemplateLookup_GetRegularTemplates_WhenModuleTemplateContainsInvalid }).Build()) } } - lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList, - moduleReleaseMetas), + reader := NewFakeModuleTemplateReader(*givenTemplateList, + moduleReleaseMetas) + lookup := templatelookup.NewTemplateLookup(reader, provider.NewCachedDescriptorProvider(), - maintenanceWindowStub{}) + moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies([]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 +816,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 +835,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 +843,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.NewModuleTemplateInfoLookupStrategies([]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 +986,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.NewModuleTemplateInfoLookupStrategies([]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,13 +1091,53 @@ 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) } }) } } +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(context.TODO(), 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.ModuleTemplate.Spec.Version) + } + } + }) + } +} + func generateModuleTemplateListWithModule(moduleName, moduleChannel, moduleVersion string) v1beta2.ModuleTemplateList { templateList := v1beta2.ModuleTemplateList{} templateList.Items = append(templateList.Items, *builder.NewModuleTemplateBuilder(). @@ -1199,13 +1191,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/modulereleasemeta.go b/pkg/testutils/modulereleasemeta.go index be4d837bea..0e2e808291 100644 --- a/pkg/testutils/modulereleasemeta.go +++ b/pkg/testutils/modulereleasemeta.go @@ -12,7 +12,11 @@ import ( "github.com/kyma-project/lifecycle-manager/pkg/util" ) -var ErrNotExpectedChannelVersion = errors.New("channel-version pair not found") +var ( + ErrNotExpectedChannelVersion = errors.New("channel-version pair not found") + ErrBetaValueNotCorrect = errors.New("beta value not correct") + ErrInternalValueNotCorrect = errors.New("internal value not correct") +) func UpdateChannelVersionInModuleReleaseMeta(ctx context.Context, clnt client.Client, moduleName, namespace, channel, version string, @@ -75,7 +79,9 @@ func SetModuleReleaseMetaBeta(ctx context.Context, beta bool, moduleName, namesp return nil } -func SetModuleReleaseMetaInternal(ctx context.Context, internal bool, moduleName, namespace string, clnt client.Client) error { +func SetModuleReleaseMetaInternal(ctx context.Context, internal bool, moduleName, namespace string, + clnt client.Client, +) error { mrm, err := GetModuleReleaseMeta(ctx, moduleName, namespace, clnt) if err != nil { return fmt.Errorf("failed to fetch modulereleasemeta, %w", err) @@ -147,3 +153,33 @@ func UpdateAllModuleReleaseMetaChannelVersions(ctx context.Context, client clien } return nil } + +func ModuleReleaseMetaBetaValueIsCorrect(ctx context.Context, client client.Client, namespace, name string, + expectedValue bool, +) error { + meta := &v1beta2.ModuleReleaseMeta{} + if err := client.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, meta); err != nil { + return err + } + + if meta.IsBeta() != expectedValue { + return ErrBetaValueNotCorrect + } + + return nil +} + +func ModuleReleaseMetaInternalValueIsCorrect(ctx context.Context, client client.Client, namespace, name string, + expectedValue bool, +) error { + meta := &v1beta2.ModuleReleaseMeta{} + if err := client.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, meta); err != nil { + return err + } + + if meta.IsInternal() != expectedValue { + return ErrInternalValueNotCorrect + } + + return nil +} diff --git a/pkg/testutils/moduletemplate.go b/pkg/testutils/moduletemplate.go index 707dcb8a07..a649e4cde0 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{}) + moduleTemplateInfoLookupStrategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies([]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 := moduleTemplateInfoLookupStrategies.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/scripts/tests/version.sh b/scripts/tests/version.sh index 94e20333d5..999d0c81d7 100755 --- a/scripts/tests/version.sh +++ b/scripts/tests/version.sh @@ -4,12 +4,15 @@ # Using a simplified version of semantic versioning regex pattern, which is bash compatible SEM_VER_REGEX="^([0-9]+)\.([0-9]+)\.([0-9]+)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$" +# Change to root directory of the project +cd "$(git rev-parse --show-toplevel)" + # Set default values for variables -KUBECTL_VERSION_DEFAULT=$(yq e '.kubectl' versions.yaml) -GO_VERSION_DEFAULT=$(yq e '.go' versions.yaml) -K3D_VERSION_DEFAULT=$(yq e '.k3d' versions.yaml) -DOCKER_VERSION_DEFAULT=$(yq e '.docker' versions.yaml) -ISTIOCTL_VERSION_DEFAULT=$(yq e '.istio' versions.yaml) +KUBECTL_VERSION_DEFAULT=$(yq e '.kubectl' ./versions.yaml) +GO_VERSION_DEFAULT=$(yq e '.go' ./versions.yaml) +K3D_VERSION_DEFAULT=$(yq e '.k3d' ./versions.yaml) +DOCKER_VERSION_DEFAULT=$(yq e '.docker' ./versions.yaml) +ISTIOCTL_VERSION_DEFAULT=$(yq e '.istio' ./versions.yaml) versioning_error=false # Check if required tools are installed diff --git a/tests/e2e/module_deletion_test.go b/tests/e2e/module_deletion_test.go index 663b1ebab9..8387af78c6 100644 --- a/tests/e2e/module_deletion_test.go +++ b/tests/e2e/module_deletion_test.go @@ -10,6 +10,7 @@ import ( . "github.com/onsi/gomega" . "github.com/kyma-project/lifecycle-manager/pkg/testutils" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" ) @@ -272,14 +273,19 @@ var _ = Describe("Non Blocking Kyma Module Deletion", Ordered, func() { It("When ModuleTemplate is removed from KCP Cluster", func() { Eventually(DeleteModuleTemplate). WithContext(ctx). - WithArguments(kcpClient, module, kyma.Spec.Channel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Succeed()) }) It("Then ModuleTemplate is no longer in SKR Cluster", func() { Eventually(ModuleTemplateExists). WithContext(ctx). - WithArguments(skrClient, module, kyma.Spec.Channel, RemoteNamespace). + WithArguments(skrClient, + module, + builder.NewKymaBuilder(). + WithName(defaultRemoteKymaName). + WithNamespace(shared.DefaultRemoteNamespace). + Build()). 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..b6a8ee449a 100644 --- a/tests/e2e/modulereleasemeta_sync_test.go +++ b/tests/e2e/modulereleasemeta_sync_test.go @@ -14,17 +14,26 @@ import ( var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) + var skrKyma *v1beta2.Kyma module := NewTemplateOperator(v1beta2.DefaultChannel) v1Version := "1.1.1-e2e-test" v2Version := "2.4.2-e2e-test" InitEmptyKymaBeforeAll(kyma) - Context("Given SKR Cluster with ModuleTemplate", func() { + Context("Given SKR Cluster", func() { + It("When Kyma can be fetched from SKR Cluster", func() { + var err error + skrKyma, err = GetKyma(ctx, skrClient, shared.DefaultRemoteKymaName, RemoteNamespace) + if err != nil { + Fail("Failed to get SKR Kyma") + } + }) + It("When Template Operator v1 ModuleTemplate is applied in the KCP Cluster with ModuleReleaseMeta", 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 +44,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, skrKyma). Should(Succeed()) By("And the ModuleReleaseMeta exists on the KCP Cluster with the correct channel-version") @@ -59,6 +68,45 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { WithContext(ctx). WithArguments(module.Name, RemoteNamespace, v1beta2.DefaultChannel, v1Version, skrClient). Should(Succeed()) + + By("And the ModuleReleaseMeta has the correct beta and internal values on the SKR Cluster") + Eventually(ModuleReleaseMetaBetaValueIsCorrect). + WithContext(ctx). + WithArguments(skrClient, RemoteNamespace, module.Name, false). + Should(Succeed()) + + Eventually(ModuleReleaseMetaInternalValueIsCorrect). + WithContext(ctx). + WithArguments(skrClient, RemoteNamespace, module.Name, false). + Should(Succeed()) + }) + + It("When Beta value is set to true on the SKR Cluster", func() { + Eventually(SetModuleReleaseMetaBeta). + WithContext(ctx). + WithArguments(true, module.Name, RemoteNamespace, skrClient). + Should(Succeed()) + }) + + It("Then Beta value is reverted back to its value from the KCP Cluster", func() { + Eventually(ModuleReleaseMetaBetaValueIsCorrect). + WithContext(ctx). + WithArguments(skrClient, RemoteNamespace, module.Name, false). + Should(Succeed()) + }) + + It("When Internal value is set to true on the SKR Cluster", func() { + Eventually(SetModuleReleaseMetaInternal). + WithContext(ctx). + WithArguments(true, module.Name, RemoteNamespace, skrClient). + Should(Succeed()) + }) + + It("Then Internal value is reverted back to its value from the KCP Cluster", func() { + Eventually(ModuleReleaseMetaInternalValueIsCorrect). + WithContext(ctx). + WithArguments(skrClient, RemoteNamespace, module.Name, false). + Should(Succeed()) }) It("When the ModuleReleaseMeta is set to beta", func() { @@ -80,7 +128,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, skrKyma). Should(Equal(ErrNotFound)) }) @@ -99,7 +147,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, skrKyma). Should(Succeed()) }) @@ -122,7 +170,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, skrKyma). Should(Equal(ErrNotFound)) }) @@ -141,26 +189,26 @@ 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, skrKyma). Should(Succeed()) }) It("When Template Operator v1 ModuleTemplate is removed from the KCP Cluster", func() { Eventually(DeleteModuleTemplate). WithContext(ctx). - WithArguments(kcpClient, module, v1beta2.DefaultChannel, ControlPlaneNamespace). + WithArguments(kcpClient, module, kyma). Should(Succeed()) 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, skrKyma). Should(Equal(ErrNotFound)) }) @@ -168,7 +216,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { By("And ModuleReleaseMeta is updated with the correct channel-version") Eventually(UpdateChannelVersionInModuleReleaseMeta). WithContext(ctx). - WithArguments(kcpClient, module.Name, ControlPlaneNamespace, v1beta2.DefaultChannel, NewerVersion). + WithArguments(kcpClient, module.Name, ControlPlaneNamespace, v1beta2.DefaultChannel, v2Version). Should(Succeed()) Eventually(ImmediatelyRequeueKyma). WithContext(ctx). @@ -178,13 +226,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, skrKyma). Should(Succeed()) By("And the ModuleReleaseMeta exists on the KCP Cluster with the correct channel-version") @@ -195,7 +243,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { Eventually(ModuleReleaseMetaContainsCorrectChannelVersion). WithContext(ctx). - WithArguments(module.Name, ControlPlaneNamespace, v1beta2.DefaultChannel, NewerVersion, kcpClient). + WithArguments(module.Name, ControlPlaneNamespace, v1beta2.DefaultChannel, v2Version, kcpClient). Should(Succeed()) By("And the ModuleReleaseMeta exists on the SKR Cluster with the correct channel-version") @@ -206,7 +254,7 @@ var _ = Describe("ModuleReleaseMeta Sync", Ordered, func() { Eventually(ModuleReleaseMetaContainsCorrectChannelVersion). WithContext(ctx). - WithArguments(module.Name, RemoteNamespace, v1beta2.DefaultChannel, NewerVersion, skrClient). + WithArguments(module.Name, RemoteNamespace, v1beta2.DefaultChannel, v2Version, skrClient). Should(Succeed()) }) diff --git a/tests/e2e/rbac_privileges_test.go b/tests/e2e/rbac_privileges_test.go index 1014f0fe90..588d2d1a34 100644 --- a/tests/e2e/rbac_privileges_test.go +++ b/tests/e2e/rbac_privileges_test.go @@ -199,38 +199,6 @@ var _ = Describe("RBAC Privileges", func() { Expect(GetRoleBindingRolePolicyRules(ctx, kcpClient, "klm-controller-manager-watcher-certmanager", "istio-system", istioSystemKlmRoleBindings)).To(Equal(istioNamespaceRoleRules)) - - By("And KLM Service Account has the correct RoleBindings in kyma-system namespace") - remoteNamespaceRoleRules := []apirbacv1.PolicyRule{ - { - APIGroups: []string{"operator.kyma-project.io"}, - Resources: []string{"kymas"}, - Verbs: []string{"list", "watch", "delete", "get", "create", "patch", "update"}, - }, - { - APIGroups: []string{"operator.kyma-project.io"}, - Resources: []string{"kymas/finalizers"}, - Verbs: []string{"update"}, - }, - { - APIGroups: []string{"operator.kyma-project.io"}, - Resources: []string{"kymas/status"}, - Verbs: []string{"get", "patch", "update", "watch"}, - }, - { - APIGroups: []string{"operator.kyma-project.io"}, - Resources: []string{"moduletemplates"}, - Verbs: []string{"list", "watch", "delete"}, - }, - } - kymaSystemKlmRoleBindings, err := ListKlmRoleBindings(kcpClient, ctx, "klm-controller-manager", - "kyma-system") - Expect(err).ToNot(HaveOccurred()) - Expect(kymaSystemKlmRoleBindings.Items).To(HaveLen(1)) - - Expect(GetRoleBindingRolePolicyRules(ctx, kcpClient, - "klm-controller-manager-skr", "kyma-system", - kymaSystemKlmRoleBindings)).To(Equal(remoteNamespaceRoleRules)) }) }) }) diff --git a/tests/integration/controller/eventfilters/suite_test.go b/tests/integration/controller/eventfilters/suite_test.go index 73d8354129..30ccfe248c 100644 --- a/tests/integration/controller/eventfilters/suite_test.go +++ b/tests/integration/controller/eventfilters/suite_test.go @@ -124,7 +124,7 @@ var _ = BeforeSuite(func() { BindAddress: randomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) 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..bcee3a7c93 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, skrKyma).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, skrKyma). 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", skrKyma). 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, skrKyma). Should(Succeed()) }) diff --git a/tests/integration/controller/kcp/suite_test.go b/tests/integration/controller/kcp/suite_test.go index 784209be82..fda586c6ed 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" @@ -124,7 +124,7 @@ var _ = BeforeSuite(func() { BindAddress: UseRandomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) @@ -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.NewModuleTemplateInfoLookupStrategies([]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..8ce38b9a6a 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" @@ -122,7 +122,7 @@ var _ = BeforeSuite(func() { BindAddress: randomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) @@ -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.NewModuleTemplateInfoLookupStrategies([]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{ + moduletemplateinfolookup.NewByVersionStrategy(kcpClient), + moduletemplateinfolookup.NewByChannelStrategy(kcpClient), + moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(kcpClient), + })), }).SetupWithManager(mgr, ctrlruntime.Options{ RateLimiter: internal.RateLimiter( 1*time.Second, 5*time.Second, diff --git a/tests/integration/controller/mandatorymodule/deletion/suite_test.go b/tests/integration/controller/mandatorymodule/deletion/suite_test.go index 368fe36e80..2ed0011137 100644 --- a/tests/integration/controller/mandatorymodule/deletion/suite_test.go +++ b/tests/integration/controller/mandatorymodule/deletion/suite_test.go @@ -106,7 +106,7 @@ var _ = BeforeSuite(func() { BindAddress: useRandomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/mandatorymodule/installation/suite_test.go b/tests/integration/controller/mandatorymodule/installation/suite_test.go index 6a77125541..38fb3eec1d 100644 --- a/tests/integration/controller/mandatorymodule/installation/suite_test.go +++ b/tests/integration/controller/mandatorymodule/installation/suite_test.go @@ -97,7 +97,7 @@ var _ = BeforeSuite(func() { BindAddress: useRandomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/manifest/custom_resource_check/suite_test.go b/tests/integration/controller/manifest/custom_resource_check/suite_test.go index 4d4059fb30..5073fede57 100644 --- a/tests/integration/controller/manifest/custom_resource_check/suite_test.go +++ b/tests/integration/controller/manifest/custom_resource_check/suite_test.go @@ -114,7 +114,7 @@ var _ = BeforeSuite(func() { if !found { metricsBindAddress = ":0" } - cacheOpts := internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace) + cacheOpts := internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace) syncPeriod := 2 * time.Second cacheOpts.SyncPeriod = &syncPeriod diff --git a/tests/integration/controller/manifest/suite_test.go b/tests/integration/controller/manifest/suite_test.go index c79bbc1cba..a6967ac2ee 100644 --- a/tests/integration/controller/manifest/suite_test.go +++ b/tests/integration/controller/manifest/suite_test.go @@ -125,7 +125,7 @@ var _ = BeforeSuite(func() { BindAddress: metricsBindAddress, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }, ) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/moduletemplate/suite_test.go b/tests/integration/controller/moduletemplate/suite_test.go index b0932cb05b..52fcd7f364 100644 --- a/tests/integration/controller/moduletemplate/suite_test.go +++ b/tests/integration/controller/moduletemplate/suite_test.go @@ -90,7 +90,7 @@ var _ = BeforeSuite(func() { BindAddress: randomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/purge/suite_test.go b/tests/integration/controller/purge/suite_test.go index f028acd694..a117dbaef7 100644 --- a/tests/integration/controller/purge/suite_test.go +++ b/tests/integration/controller/purge/suite_test.go @@ -101,7 +101,7 @@ var _ = BeforeSuite(func() { BindAddress: useRandomPort, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) diff --git a/tests/integration/controller/withwatcher/suite_test.go b/tests/integration/controller/withwatcher/suite_test.go index d481c9d137..2b9c96f205 100644 --- a/tests/integration/controller/withwatcher/suite_test.go +++ b/tests/integration/controller/withwatcher/suite_test.go @@ -145,7 +145,7 @@ var _ = BeforeSuite(func() { BindAddress: metricsBindAddress, }, Scheme: k8sclientscheme.Scheme, - Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace, RemoteNamespace), + Cache: internal.GetCacheOptions(false, "istio-system", ControlPlaneNamespace), }) Expect(err).ToNot(HaveOccurred()) diff --git a/unit-test-coverage.yaml b/unit-test-coverage.yaml index 1e1b9a09f3..4bfc67663c 100644 --- a/unit-test-coverage.yaml +++ b/unit-test-coverage.yaml @@ -19,4 +19,5 @@ packages: internal/pkg/resources: 91.7 internal/remote: 20.2 internal/util/collections: 86 - pkg/templatelookup: 83.3 + pkg/templatelookup: 88 + pkg/templatelookup/moduletemplateinfolookup: 72 diff --git a/versions.yaml b/versions.yaml index 7b4c7dc60c..65626ff6ac 100644 --- a/versions.yaml +++ b/versions.yaml @@ -1,12 +1,13 @@ # defines the versions of the tools used in the project -istio: "1.24.1" -k3d: "5.7.4" -modulectl: "1.1.5" certManager: "1.15.0" -k8s: "1.30.3" -kustomize: "5.3.0" controllerTools: "0.14.0" +docker: "27.4.0" +go: "1.23.4" golangciLint: "1.60.3" +istio: "1.24.1" +k3d: "5.7.4" +k8s: "1.30.3" kubectl: "1.31.3" -go: "1.23.4" -docker: "27.4.0" +kustomize: "5.3.0" +modulectl: "1.1.5" +yq: "4.45.1"