diff --git a/.golangci.yaml b/.golangci.yaml index d5c184f292..a9d6a735c1 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -190,7 +190,7 @@ issues: linters: [ gci ] # Disable gci due to the test utilities dot import. - path: tests/integration/declarative/declarative_test.go linters: [ gci ] # Disable gci due to the test utilities dot import. - - path: tests/integration/controller/(controlplane|eventfilters|kyma|withwatcher|purge|mandatorymodule)/(.*)_test.go + - path: tests/integration/controller/(eventfilters|kyma|withwatcher|purge|mandatorymodule|kcp)/(.*)_test.go linters: [ gci ] # Disable gci due to the test utilities dot import. - linters: - importas diff --git a/api/go.mod b/api/go.mod index 261b578a8d..250ed799eb 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,7 +5,7 @@ go 1.22.4 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/open-component-model/ocm v0.11.0 - k8s.io/apimachinery v0.30.2 + k8s.io/apimachinery v0.30.3 sigs.k8s.io/controller-runtime v0.18.4 ) diff --git a/api/go.sum b/api/go.sum index 671718c1ae..a1d22d3099 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1052,8 +1052,8 @@ k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4= -k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= -k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc= +k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= diff --git a/api/v1beta2/kyma_types.go b/api/v1beta2/kyma_types.go index a12135741b..110d9073c1 100644 --- a/api/v1beta2/kyma_types.go +++ b/api/v1beta2/kyma_types.go @@ -61,10 +61,7 @@ type Module struct { // Name is a unique identifier of the module. // It is used to resolve a ModuleTemplate for creating a set of resources on the cluster. // - // Name can be one of 3 kinds: - // - The ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module - // - The Name or Namespace/Name of a ModuleTemplate, e.g. my-moduletemplate or kyma-system/my-moduletemplate - // - The FQDN, e.g. kyma-project.io/module/my-module as located in .spec.descriptor.component.name + // Name can only be the ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module Name string `json:"name"` // ControllerName is able to set the controller used for reconciliation of the module. It can be used diff --git a/cmd/main.go b/cmd/main.go index 45323217d1..45ad9ae23b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -177,10 +177,11 @@ func setupManager(flagVar *flags.FlagVar, cacheOptions cache.Options, scheme *ma } sharedMetrics := metrics.NewSharedMetrics() - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() kymaMetrics := metrics.NewKymaMetrics(sharedMetrics) mandatoryModulesMetrics := metrics.NewMandatoryModulesMetrics() - setupKymaReconciler(mgr, descriptorProvider, skrContextProvider, eventRecorder, flagVar, options, skrWebhookManager, kymaMetrics, + setupKymaReconciler(mgr, descriptorProvider, skrContextProvider, eventRecorder, flagVar, options, skrWebhookManager, + kymaMetrics, setupLog) setupManifestReconciler(mgr, flagVar, options, sharedMetrics, mandatoryModulesMetrics, setupLog) setupMandatoryModuleReconciler(mgr, descriptorProvider, flagVar, options, mandatoryModulesMetrics, setupLog) @@ -315,7 +316,9 @@ func setupKymaReconciler(mgr ctrl.Manager, } } -func createSkrWebhookManager(mgr ctrl.Manager, skrContextFactory remote.SkrContextProvider, flagVar *flags.FlagVar) (*watcher.SKRWebhookManifestManager, error) { +func createSkrWebhookManager(mgr ctrl.Manager, skrContextFactory remote.SkrContextProvider, + flagVar *flags.FlagVar, +) (*watcher.SKRWebhookManifestManager, error) { caCertificateCache := watcher.NewCACertificateCache(flagVar.CaCertCacheTTL) config := watcher.SkrWebhookManagerConfig{ SKRWatcherPath: flagVar.WatcherResourcesPath, @@ -397,7 +400,9 @@ func setupManifestReconciler(mgr ctrl.Manager, flagVar *flags.FlagVar, options c if err := manifest.SetupWithManager( mgr, options, queue.RequeueIntervals{ Success: flagVar.ManifestRequeueSuccessInterval, - Busy: flagVar.KymaRequeueBusyInterval, + Busy: flagVar.ManifestRequeueBusyInterval, + Error: flagVar.ManifestRequeueErrInterval, + Warning: flagVar.ManifestRequeueWarningInterval, }, manifest.SetupOptions{ ListenerAddr: flagVar.ManifestListenerAddr, EnableDomainNameVerification: flagVar.EnableDomainNameVerification, diff --git a/config/crd/bases/operator.kyma-project.io_kymas.yaml b/config/crd/bases/operator.kyma-project.io_kymas.yaml index f96c74b3e7..a4927b64a9 100644 --- a/config/crd/bases/operator.kyma-project.io_kymas.yaml +++ b/config/crd/bases/operator.kyma-project.io_kymas.yaml @@ -96,10 +96,7 @@ spec: It is used to resolve a ModuleTemplate for creating a set of resources on the cluster. - Name can be one of 3 kinds: - - The ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module - - The Name or Namespace/Name of a ModuleTemplate, e.g. my-moduletemplate or kyma-system/my-moduletemplate - - The FQDN, e.g. kyma-project.io/module/my-module as located in .spec.descriptor.component.name + Name can only be the ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module type: string remoteModuleTemplateRef: description: |- @@ -539,10 +536,7 @@ spec: It is used to resolve a ModuleTemplate for creating a set of resources on the cluster. - Name can be one of 3 kinds: - - The ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module - - The Name or Namespace/Name of a ModuleTemplate, e.g. my-moduletemplate or kyma-system/my-moduletemplate - - The FQDN, e.g. kyma-project.io/module/my-module as located in .spec.descriptor.component.name + Name can only be the ModuleName label value of the module-template, e.g. operator.kyma-project.io/module-name=my-module type: string remoteModuleTemplateRef: description: |- diff --git a/docs/developer-tutorials/local-test-setup.md b/docs/developer-tutorials/local-test-setup.md index 0dfb213166..f4ef4f6c6c 100644 --- a/docs/developer-tutorials/local-test-setup.md +++ b/docs/developer-tutorials/local-test-setup.md @@ -1,5 +1,17 @@ # Local test Setup in the control-plane Mode Using k3d +> ### Supported Versions +> * Golang: `v1.22.5` +> * k3d: `v5.6.0` +> * k3s: `v1.27.4-k3s1 (default)` +> * kubectl: +> * Client Version: `v1.30.2` +> * Server Version: `v1.27.4+k3s1` +> * docker: +> * Client Version: `v26.1.4` +> * Server: `Docker Desktop v4.31.0` +> * Engine Version: `v26.1.4` + ## Context This tutorial shows how to configure a fully working e2e test setup including the following components: @@ -184,36 +196,33 @@ k3d cluster create skr-local 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: + ```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 - sync: - enabled: true - modules: - - name: template-operator - EOF + 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 diff --git a/docs/technical-reference/api/kyma-cr.md b/docs/technical-reference/api/kyma-cr.md index b8dd0272db..02ea4366e0 100644 --- a/docs/technical-reference/api/kyma-cr.md +++ b/docs/technical-reference/api/kyma-cr.md @@ -62,43 +62,16 @@ spec: name: kyma-project.io/module/sample ``` -The module mentioned above can be referenced in one of the following ways: - -* The label value of `operator.kyma-project.io/module-name`: - - ```yaml - spec: - channel: regular - modules: - - name: module-name-from-label - ``` - -* The name or namespace/name of a ModuleTemplate CR: - - ```yaml - spec: - channel: regular - modules: - - name: moduletemplate-sample - ``` - - or - - ```yaml - spec: - channel: regular - modules: - - name: default/moduletemplate-sample - ``` - -* The fully qualified name of the descriptor as located in **.spec.descriptor.component.name**: - - ```yaml - spec: - channel: regular - modules: - - name: kyma-project.io/module/sample - ``` +The module mentioned above can *only* be referenced using the label value of `operator.kyma-project.io/module-name`: +```yaml +spec: + channel: regular + modules: + - name: module-name-from-label +``` + +> **CAUTION:** +> Module referencing using NamespacedName and FQDN (Fully Qualified Domain Name) has been deprecated. ### **.spec.modules[].managed** diff --git a/docs/user-tutorials/01-10-control-plane-quick-start.md b/docs/user-tutorials/01-10-control-plane-quick-start.md index d7506fe4f7..8cc8354d40 100644 --- a/docs/user-tutorials/01-10-control-plane-quick-start.md +++ b/docs/user-tutorials/01-10-control-plane-quick-start.md @@ -39,7 +39,9 @@ To use Lifecycle Manager in a local setup, you need the following prerequisites: kubectl apply -f https://raw.githubusercontent.com/prometheus-community/helm-charts/main/charts/kube-prometheus-stack/charts/crds/crds/crd-servicemonitors.yaml ``` -You can also follow the official [Prometheus Operator quick start](https://prometheus-operator.dev/docs/getting-started/quick-start/) guide to deploy a full set of Prometheus Operator features into your cluster. +You can also follow the +official [Prometheus Operator quick start](https://prometheus-operator.dev/docs/getting-started/) guide to deploy a full +set of Prometheus Operator features into your cluster. ### Deploy Lifecycle Manager diff --git a/go.mod b/go.mod index 6bd336fd4c..d7a9b4b03f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-logr/logr v1.4.2 github.com/go-logr/zapr v1.3.0 github.com/golang/mock v1.6.0 - github.com/google/go-containerregistry v0.20.0 + github.com/google/go-containerregistry v0.20.1 github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20231202142526-55ffb0092afd github.com/jellydator/ttlcache/v3 v3.2.0 github.com/kyma-project/lifecycle-manager/api v0.0.0-00010101000000-000000000000 @@ -29,20 +29,20 @@ require ( ) require ( - istio.io/api v1.22.2 - istio.io/client-go v1.22.2 + istio.io/api v1.22.3 + istio.io/client-go v1.22.3 ) require ( github.com/go-co-op/gocron v1.37.0 github.com/kyma-project/template-operator/api v0.0.0-20240404131948-52c84f14e73c github.com/prometheus/client_model v0.6.1 - k8s.io/api v0.30.2 - k8s.io/apiextensions-apiserver v0.30.2 - k8s.io/apimachinery v0.30.2 - k8s.io/cli-runtime v0.30.2 - k8s.io/client-go v0.30.2 - k8s.io/kubectl v0.30.2 + k8s.io/api v0.30.3 + k8s.io/apiextensions-apiserver v0.30.3 + k8s.io/apimachinery v0.30.3 + k8s.io/cli-runtime v0.30.3 + k8s.io/client-go v0.30.3 + k8s.io/kubectl v0.30.3 ) require ( @@ -319,7 +319,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect helm.sh/helm/v3 v3.15.1 // indirect - k8s.io/component-base v0.30.2 // indirect + k8s.io/component-base v0.30.3 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect oras.land/oras-go v1.2.5 // indirect diff --git a/go.sum b/go.sum index b153808eea..64035e7e5f 100644 --- a/go.sum +++ b/go.sum @@ -467,8 +467,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg= -github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0= +github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20231202142526-55ffb0092afd h1:RkbnRtHTdBpYmp0Simm3fDUTYNVbmX4aVwdgflHLfdg= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20231202142526-55ffb0092afd/go.mod h1:5sSbf/SbGGvjWIlMlt2bkEqOq+ufOIBYrBevLuxbfSs= github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI= @@ -1214,28 +1214,28 @@ helm.sh/helm/v3 v3.15.1 h1:22ztacHz4gMqhXNqCQ9NAg6BFWoRUryNLvnkz6OVyw0= helm.sh/helm/v3 v3.15.1/go.mod h1:fvfoRcB8UKRUV5jrIfOTaN/pG1TPhuqSb56fjYdTKXg= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -istio.io/api v1.22.2 h1:b02rTNfbnsEK2HMH/kfuXHTzovSmqcL5cAj2TSklPcQ= -istio.io/api v1.22.2/go.mod h1:S3l8LWqNYS9yT+d4bH+jqzH2lMencPkW7SKM1Cu9EyM= -istio.io/client-go v1.22.2 h1:BiE7itlXFTHpZwOv0t2aZQGga7oCox8lYOdaYbyWNEo= -istio.io/client-go v1.22.2/go.mod h1:Fxt0tVZLXQRKyrBv7uwm4zCZE0qayejG0bSwZy9K6Hg= -k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= -k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= -k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE= -k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw= -k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= -k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/cli-runtime v0.30.2 h1:ooM40eEJusbgHNEqnHziN9ZpLN5U4WcQGsdLKVxpkKE= -k8s.io/cli-runtime v0.30.2/go.mod h1:Y4g/2XezFyTATQUbvV5WaChoUGhojv/jZAtdp5Zkm0A= -k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50= -k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs= -k8s.io/component-base v0.30.2 h1:pqGBczYoW1sno8q9ObExUqrYSKhtE5rW3y6gX88GZII= -k8s.io/component-base v0.30.2/go.mod h1:yQLkQDrkK8J6NtP+MGJOws+/PPeEXNpwFixsUI7h/OE= +istio.io/api v1.22.3 h1:V59wgcCm2fK2r137QBsddCDHNg0efg/DauIWEB9DFz8= +istio.io/api v1.22.3/go.mod h1:S3l8LWqNYS9yT+d4bH+jqzH2lMencPkW7SKM1Cu9EyM= +istio.io/client-go v1.22.3 h1:4WocGQYVTASpfn7tj1yGE8f0sgxzbxOkg56HX1LJQ5U= +istio.io/client-go v1.22.3/go.mod h1:D/vNne1n5586423NgGXMnPgshE/99mQgnjnxK/Vw2yM= +k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= +k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04= +k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U= +k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4= +k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc= +k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/cli-runtime v0.30.3 h1:aG69oRzJuP2Q4o8dm+f5WJIX4ZBEwrvdID0+MXyUY6k= +k8s.io/cli-runtime v0.30.3/go.mod h1:hwrrRdd9P84CXSKzhHxrOivAR9BRnkMt0OeP5mj7X30= +k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= +k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= +k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s= +k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f/go.mod h1:S9tOR0FxgyusSNR+MboCuiDpVWkAifZvaYI1Q2ubgro= -k8s.io/kubectl v0.30.2 h1:cgKNIvsOiufgcs4yjvgkK0+aPCfa8pUwzXdJtkbhsH8= -k8s.io/kubectl v0.30.2/go.mod h1:rz7GHXaxwnigrqob0lJsiA07Df8RE3n1TSaC2CTeuB4= +k8s.io/kubectl v0.30.3 h1:YIBBvMdTW0xcDpmrOBzcpUVsn+zOgjMYIu7kAq+yqiI= +k8s.io/kubectl v0.30.3/go.mod h1:IcR0I9RN2+zzTRUa1BzZCm4oM0NLOawE6RzlDvd1Fpo= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= diff --git a/internal/declarative/v2/reconciler.go b/internal/declarative/v2/reconciler.go index 91de58d41b..f7d93cb2d2 100644 --- a/internal/declarative/v2/reconciler.go +++ b/internal/declarative/v2/reconciler.go @@ -179,7 +179,8 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return r.finishReconcile(ctx, manifest, metrics.ManifestRenderResources, manifestStatus, err) } - if err := r.pruneDiff(ctx, skrClient, manifest, current, target, spec); errors.Is(err, resources.ErrDeletionNotFinished) { + if err := r.pruneDiff(ctx, skrClient, manifest, current, target, spec); errors.Is(err, + resources.ErrDeletionNotFinished) { r.ManifestMetrics.RecordRequeueReason(metrics.ManifestPruneDiffNotFinished, queue.IntendedRequeue) return ctrl.Result{Requeue: true}, nil } else if err != nil { @@ -219,8 +220,8 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return r.finishReconcile(ctx, manifest, metrics.ManifestReconcileFinished, manifestStatus, nil) } -func (r *Reconciler) cleanupManifest(ctx context.Context, req ctrl.Request, manifest *v1beta2.Manifest, manifestStatus shared.Status, - requeueReason metrics.ManifestRequeueReason, originalErr error, +func (r *Reconciler) cleanupManifest(ctx context.Context, req ctrl.Request, manifest *v1beta2.Manifest, + manifestStatus shared.Status, requeueReason metrics.ManifestRequeueReason, originalErr error, ) (ctrl.Result, error) { r.ManifestMetrics.RemoveManifestDuration(req.Name) r.cleanUpMandatoryModuleMetrics(manifest) @@ -299,10 +300,7 @@ func (r *Reconciler) initialize(manifest *v1beta2.Manifest) error { return nil } -func (r *Reconciler) renderResources( - ctx context.Context, - skrClient Client, - manifest *v1beta2.Manifest, +func (r *Reconciler) renderResources(ctx context.Context, skrClient Client, manifest *v1beta2.Manifest, spec *Spec, ) ([]*resource.Info, []*resource.Info, error) { resourceCondition := newResourcesCondition(manifest) @@ -392,9 +390,9 @@ func hasDiff(oldResources []shared.Resource, newResources []shared.Resource) boo return false } -func (r *Reconciler) checkDeploymentState( - ctx context.Context, clnt Client, target []*resource.Info, -) (shared.State, error) { +func (r *Reconciler) checkDeploymentState(ctx context.Context, clnt Client, target []*resource.Info) (shared.State, + error, +) { resourceReadyCheck := r.CustomReadyCheck deploymentState, err := resourceReadyCheck.Run(ctx, clnt, target) @@ -448,12 +446,8 @@ func (r *Reconciler) removeModuleCR(ctx context.Context, clnt Client, manifest * return nil } -func (r *Reconciler) renderTargetResources( - ctx context.Context, - skrClient client.Client, - converter ResourceToInfoConverter, - manifest *v1beta2.Manifest, - spec *Spec, +func (r *Reconciler) renderTargetResources(ctx context.Context, skrClient client.Client, + converter ResourceToInfoConverter, manifest *v1beta2.Manifest, spec *Spec, ) ([]*resource.Info, error) { if !manifest.GetDeletionTimestamp().IsZero() { deleted, err := checkCRDeletion(ctx, skrClient, manifest) @@ -515,12 +509,8 @@ func checkCRDeletion(ctx context.Context, skrClient client.Client, manifest *v1b return false, nil } -func (r *Reconciler) pruneDiff( - ctx context.Context, - clnt Client, - manifest *v1beta2.Manifest, - current, target []*resource.Info, - spec *Spec, +func (r *Reconciler) pruneDiff(ctx context.Context, clnt Client, manifest *v1beta2.Manifest, + current, target []*resource.Info, spec *Spec, ) error { diff, err := pruneResource(ResourceList(current).Difference(target), "Namespace", namespaceNotBeRemoved) if err != nil { @@ -652,10 +642,13 @@ func (r *Reconciler) finishReconcile(ctx context.Context, manifest *v1beta2.Mani return ctrl.Result{}, originalErr } r.ManifestMetrics.RecordRequeueReason(requeueReason, queue.IntendedRequeue) - return ctrl.Result{RequeueAfter: r.Success}, nil + requeueAfter := queue.DetermineRequeueInterval(manifest.GetStatus().State, r.RequeueIntervals) + return ctrl.Result{RequeueAfter: requeueAfter}, nil } -func (r *Reconciler) patchStatusIfDiffExist(ctx context.Context, manifest *v1beta2.Manifest, previousStatus shared.Status) error { +func (r *Reconciler) patchStatusIfDiffExist(ctx context.Context, manifest *v1beta2.Manifest, + previousStatus shared.Status, +) error { if hasStatusDiff(manifest.GetStatus(), previousStatus) { resetNonPatchableField(manifest) if err := r.Status().Patch(ctx, manifest, client.Apply, client.ForceOwnership, defaultFieldOwner); err != nil { diff --git a/internal/descriptor/cache/key.go b/internal/descriptor/cache/key.go index 500c197e8c..643dee5742 100644 --- a/internal/descriptor/cache/key.go +++ b/internal/descriptor/cache/key.go @@ -16,7 +16,8 @@ func GenerateDescriptorKey(template *v1beta2.ModuleTemplate) DescriptorKey { moduleVersion := template.Annotations[shared.ModuleVersionAnnotation] _, err := semver.NewVersion(moduleVersion) if moduleVersion != "" && err == nil { - return DescriptorKey(fmt.Sprintf("%s:%s:%s", template.Name, template.Spec.Channel, moduleVersion)) + return DescriptorKey(fmt.Sprintf("%s:%s:%d:%s", template.Name, template.Spec.Channel, template.Generation, + moduleVersion)) } } diff --git a/internal/descriptor/cache/key_test.go b/internal/descriptor/cache/key_test.go index c40dff7672..1261dd1d69 100644 --- a/internal/descriptor/cache/key_test.go +++ b/internal/descriptor/cache/key_test.go @@ -18,16 +18,17 @@ func TestGenerateDescriptorCacheKey(t *testing.T) { want cache.DescriptorKey }{ { - name: "Annotations is not nil and valid semver", + name: "ModuleVersionAnnotation is not nil and valid semver", template: builder.NewModuleTemplateBuilder(). WithName("name"). WithAnnotation(shared.ModuleVersionAnnotation, "1.0.0"). WithChannel("channel"). + WithGeneration(1). Build(), - want: "name:channel:1.0.0", + want: "name:channel:1:1.0.0", }, { - name: "Annotations is not nil but invalid semver", + name: "ModuleVersionAnnotation is not nil but invalid semver", template: builder.NewModuleTemplateBuilder(). WithName("name"). WithGeneration(1). @@ -37,7 +38,7 @@ func TestGenerateDescriptorCacheKey(t *testing.T) { want: "name:channel:1", }, { - name: "Annotations is not nil but module version is empty", + name: "ModuleVersionAnnotation is not nil but module version is empty", template: builder.NewModuleTemplateBuilder(). WithName("name"). WithGeneration(2). @@ -47,7 +48,7 @@ func TestGenerateDescriptorCacheKey(t *testing.T) { want: "name:channel:2", }, { - name: "Annotations is nil", + name: "ModuleVersionAnnotation is nil", template: builder.NewModuleTemplateBuilder(). WithName("name"). WithGeneration(3). diff --git a/internal/descriptor/provider/provider.go b/internal/descriptor/provider/provider.go index 138d10d3db..786dddae7a 100644 --- a/internal/descriptor/provider/provider.go +++ b/internal/descriptor/provider/provider.go @@ -17,17 +17,12 @@ var ( ) type CachedDescriptorProvider struct { - descriptorCache *cache.DescriptorCache + DescriptorCache *cache.DescriptorCache } -func NewCachedDescriptorProvider(descriptorCache *cache.DescriptorCache) *CachedDescriptorProvider { - if descriptorCache != nil { - return &CachedDescriptorProvider{ - descriptorCache: descriptorCache, - } - } +func NewCachedDescriptorProvider() *CachedDescriptorProvider { return &CachedDescriptorProvider{ - descriptorCache: cache.NewDescriptorCache(), + DescriptorCache: cache.NewDescriptorCache(), } } @@ -49,7 +44,7 @@ func (c *CachedDescriptorProvider) GetDescriptor(template *v1beta2.ModuleTemplat return desc, nil } key := cache.GenerateDescriptorKey(template) - descriptor := c.descriptorCache.Get(key) + descriptor := c.DescriptorCache.Get(key) if descriptor != nil { return descriptor, nil } @@ -75,7 +70,7 @@ func (c *CachedDescriptorProvider) Add(template *v1beta2.ModuleTemplate) error { return ErrTemplateNil } key := cache.GenerateDescriptorKey(template) - descriptor := c.descriptorCache.Get(key) + descriptor := c.DescriptorCache.Get(key) if descriptor != nil { return nil } @@ -83,7 +78,7 @@ func (c *CachedDescriptorProvider) Add(template *v1beta2.ModuleTemplate) error { if template.Spec.Descriptor.Object != nil { desc, ok := template.Spec.Descriptor.Object.(*v1beta2.Descriptor) if ok && desc != nil { - c.descriptorCache.Set(key, desc) + c.DescriptorCache.Set(key, desc) return nil } } @@ -101,6 +96,6 @@ func (c *CachedDescriptorProvider) Add(template *v1beta2.ModuleTemplate) error { return ErrTypeAssert } - c.descriptorCache.Set(key, descriptor) + c.DescriptorCache.Set(key, descriptor) return nil } diff --git a/internal/descriptor/provider/provider_test.go b/internal/descriptor/provider/provider_test.go index 3925d74772..b526e35bf0 100644 --- a/internal/descriptor/provider/provider_test.go +++ b/internal/descriptor/provider/provider_test.go @@ -14,7 +14,7 @@ import ( ) func TestGetDescriptor_OnEmptySpec_ReturnsErrDecode(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) // assuming it handles nil cache internally + descriptorProvider := provider.NewCachedDescriptorProvider() template := &v1beta2.ModuleTemplate{} _, err := descriptorProvider.GetDescriptor(template) @@ -24,7 +24,7 @@ func TestGetDescriptor_OnEmptySpec_ReturnsErrDecode(t *testing.T) { } func TestAdd_OnNilTemplate_ReturnsErrTemplateNil(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() err := descriptorProvider.Add(nil) @@ -33,7 +33,7 @@ func TestAdd_OnNilTemplate_ReturnsErrTemplateNil(t *testing.T) { } func TestGetDescriptor_OnNilTemplate_ReturnsErrTemplateNil(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() _, err := descriptorProvider.GetDescriptor(nil) @@ -42,7 +42,7 @@ func TestGetDescriptor_OnNilTemplate_ReturnsErrTemplateNil(t *testing.T) { } func TestGetDescriptor_OnInvalidRawDescriptor_ReturnsErrDescriptorNil(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() template := builder.NewModuleTemplateBuilder().WithRawDescriptor([]byte("invalid descriptor")).WithDescriptor(nil).Build() _, err := descriptorProvider.GetDescriptor(template) @@ -52,8 +52,7 @@ func TestGetDescriptor_OnInvalidRawDescriptor_ReturnsErrDescriptorNil(t *testing } func TestGetDescriptor_OnEmptyCache_ReturnsParsedDescriptor(t *testing.T) { - descriptorCache := cache.NewDescriptorCache() - descriptorProvider := provider.NewCachedDescriptorProvider(descriptorCache) + descriptorProvider := provider.NewCachedDescriptorProvider() template := builder.NewModuleTemplateBuilder().Build() _, err := descriptorProvider.GetDescriptor(template) @@ -62,7 +61,7 @@ func TestGetDescriptor_OnEmptyCache_ReturnsParsedDescriptor(t *testing.T) { } func TestAdd_OnInvalidRawDescriptor_ReturnsErrDecode(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() template := builder.NewModuleTemplateBuilder().WithRawDescriptor([]byte("invalid descriptor")).WithDescriptor(nil).Build() err := descriptorProvider.Add(template) @@ -72,7 +71,7 @@ func TestAdd_OnInvalidRawDescriptor_ReturnsErrDecode(t *testing.T) { } func TestAdd_OnDescriptorTypeButNull_ReturnsNoError(t *testing.T) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() template := builder.NewModuleTemplateBuilder().WithDescriptor(&v1beta2.Descriptor{}).Build() err := descriptorProvider.Add(template) @@ -82,12 +81,14 @@ func TestAdd_OnDescriptorTypeButNull_ReturnsNoError(t *testing.T) { func TestGetDescriptor_OnEmptyCache_AddsDescriptorFromTemplate(t *testing.T) { descriptorCache := cache.NewDescriptorCache() - descriptorProvider := provider.NewCachedDescriptorProvider(descriptorCache) + descriptorProvider := provider.CachedDescriptorProvider{DescriptorCache: descriptorCache} expected := &v1beta2.Descriptor{ - ComponentDescriptor: &compdesc.ComponentDescriptor{Metadata: compdesc.Metadata{ - ConfiguredVersion: "v2", - }}, + ComponentDescriptor: &compdesc.ComponentDescriptor{ + Metadata: compdesc.Metadata{ + ConfiguredVersion: "v2", + }, + }, } template := builder.NewModuleTemplateBuilder().WithDescriptor(expected).Build() diff --git a/internal/pkg/flags/flags.go b/internal/pkg/flags/flags.go index 374cda47cd..8e2c327ce6 100644 --- a/internal/pkg/flags/flags.go +++ b/internal/pkg/flags/flags.go @@ -16,6 +16,9 @@ const ( DefaultKymaRequeueWarningInterval = 30 * time.Second DefaultKymaRequeueBusyInterval = 5 * time.Second DefaultManifestRequeueSuccessInterval = 30 * time.Second + DefaultManifestRequeueErrInterval = 2 * time.Second + DefaultManifestRequeueWarningInterval = 30 * time.Second + DefaultManifestRequeueBusyInterval = 5 * time.Second DefaultMandatoryModuleRequeueSuccessInterval = 30 * time.Second DefaultMandatoryModuleDeletionRequeueSuccessInterval = 30 * time.Second DefaultWatcherRequeueSuccessInterval = 30 * time.Second @@ -119,6 +122,15 @@ func DefineFlagVar() *FlagVar { flag.DurationVar(&flagVar.ManifestRequeueSuccessInterval, "manifest-requeue-success-interval", DefaultManifestRequeueSuccessInterval, "determines the duration a Manifest in Ready state is enqueued for reconciliation.") + flag.DurationVar(&flagVar.ManifestRequeueErrInterval, "manifest-requeue-error-interval", + DefaultManifestRequeueErrInterval, + "determines the duration a Manifest in Error state is enqueued for reconciliation.") + flag.DurationVar(&flagVar.ManifestRequeueWarningInterval, "manifest-requeue-warning-interval", + DefaultManifestRequeueWarningInterval, + "determines the duration a Manifest in Warning state is enqueued for reconciliation.") + flag.DurationVar(&flagVar.ManifestRequeueBusyInterval, "manifest-requeue-busy-interval", + DefaultManifestRequeueBusyInterval, + "determines the duration a Manifest in Processing state is enqueued for reconciliation.") flag.DurationVar(&flagVar.MandatoryModuleDeletionRequeueSuccessInterval, "mandatory-module-deletion-requeue-success-interval", DefaultMandatoryModuleDeletionRequeueSuccessInterval, @@ -230,6 +242,9 @@ type FlagVar struct { KymaRequeueBusyInterval time.Duration KymaRequeueWarningInterval time.Duration ManifestRequeueSuccessInterval time.Duration + ManifestRequeueErrInterval time.Duration + ManifestRequeueBusyInterval time.Duration + ManifestRequeueWarningInterval time.Duration WatcherRequeueSuccessInterval time.Duration MandatoryModuleRequeueSuccessInterval time.Duration MandatoryModuleDeletionRequeueSuccessInterval time.Duration diff --git a/internal/pkg/flags/flags_test.go b/internal/pkg/flags/flags_test.go index 706d029974..8f34ec5364 100644 --- a/internal/pkg/flags/flags_test.go +++ b/internal/pkg/flags/flags_test.go @@ -43,6 +43,21 @@ func Test_ConstantFlags(t *testing.T) { constValue: DefaultManifestRequeueSuccessInterval.String(), expectedValue: (30 * time.Second).String(), }, + { + constName: "DefaultManifestRequeueErrInterval", + constValue: DefaultManifestRequeueErrInterval.String(), + expectedValue: (2 * time.Second).String(), + }, + { + constName: "DefaultManifestRequeueWarningInterval", + constValue: DefaultManifestRequeueWarningInterval.String(), + expectedValue: (30 * time.Second).String(), + }, + { + constName: "DefaultManifestRequeueBusyInterval", + constValue: DefaultManifestRequeueBusyInterval.String(), + expectedValue: (5 * time.Second).String(), + }, { constName: "DefaultMandatoryModuleRequeueSuccessInterval", constValue: DefaultMandatoryModuleRequeueSuccessInterval.String(), diff --git a/pkg/module/sync/runner.go b/pkg/module/sync/runner.go index 3bfe8f070c..67128b563c 100644 --- a/pkg/module/sync/runner.go +++ b/pkg/module/sync/runner.go @@ -54,6 +54,11 @@ func (r *Runner) ReconcileManifests(ctx context.Context, kyma *v1beta2.Kyma, results := make(chan error, len(modules)) for _, module := range modules { go func(module *common.Module) { + // Should not happen, but in case of NPE, we should stop process further. + if module.Template == nil { + results <- nil + return + } // Due to module template visibility change, some module previously deployed should be removed. if errors.Is(module.Template.Err, templatelookup.ErrTemplateNotAllowed) { results <- r.deleteManifest(ctx, module) @@ -111,7 +116,7 @@ func (r *Runner) updateManifest(ctx context.Context, kyma *v1beta2.Kyma, } moduleStatus := kyma.GetModuleStatusMap()[module.ModuleName] - if err := r.doUpdateWithStrategy(ctx, kyma.Labels[shared.ManagedBy], module.Enabled, + if err := r.doUpdateWithStrategy(ctx, kyma.Labels[shared.ManagedBy], module, manifestObj, moduleStatus); err != nil { return err } @@ -119,7 +124,7 @@ func (r *Runner) updateManifest(ctx context.Context, kyma *v1beta2.Kyma, return nil } -func (r *Runner) doUpdateWithStrategy(ctx context.Context, owner string, isEnabledModule bool, +func (r *Runner) doUpdateWithStrategy(ctx context.Context, owner string, module *common.Module, manifestObj *v1beta2.Manifest, kymaModuleStatus *v1beta2.ModuleStatus, ) error { manifestInCluster := &v1beta2.Manifest{} @@ -133,12 +138,12 @@ func (r *Runner) doUpdateWithStrategy(ctx context.Context, owner string, isEnabl manifestInCluster = nil } - if !NeedToUpdate(manifestInCluster, manifestObj, kymaModuleStatus) { + if !NeedToUpdate(manifestInCluster, manifestObj, kymaModuleStatus, module.Template.GetGeneration()) { // Point to the current state from the cluster for the outside sync of the manifest *manifestObj = *manifestInCluster return nil } - if isEnabledModule { + if module.Enabled { return r.patchManifest(ctx, owner, manifestObj) } // For disabled module, the manifest CR is under deleting, in this case, we only update the spec when it's still not deleted. @@ -174,11 +179,15 @@ func (r *Runner) updateAvailableManifestSpec(ctx context.Context, manifestObj *v return nil } -func NeedToUpdate(manifestInCluster, manifestObj *v1beta2.Manifest, moduleStatus *v1beta2.ModuleStatus) bool { +func NeedToUpdate(manifestInCluster, manifestObj *v1beta2.Manifest, moduleStatus *v1beta2.ModuleStatus, + moduleTemplateGeneration int64, +) bool { if manifestInCluster == nil || moduleStatus == nil { // moduleStatus is nil in case of mandatory module return true } - + if moduleStatus.Template != nil && moduleStatus.Template.GetGeneration() != moduleTemplateGeneration { + return true + } return manifestObj.Spec.Version != moduleStatus.Version || manifestObj.Labels[shared.ChannelLabel] != moduleStatus.Channel || moduleStatus.State != manifestInCluster.Status.State @@ -263,8 +272,12 @@ func generateModuleStatus(module *common.Module, existStatus *v1beta2.ModuleStat moduleCRAPIVersion, moduleCRKind := manifestObject.Spec.Resource. GetObjectKind().GroupVersionKind().ToAPIVersionAndKind() moduleResource = &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMetaFromObject(manifestObject.Spec.Resource), - TypeMeta: apimetav1.TypeMeta{Kind: moduleCRKind, APIVersion: moduleCRAPIVersion}, + PartialMeta: v1beta2.PartialMeta{ + Name: manifestObject.Spec.Resource.GetName(), + Namespace: manifestObject.Spec.Resource.GetNamespace(), + Generation: manifestObject.Spec.Resource.GetGeneration(), + }, + TypeMeta: apimetav1.TypeMeta{Kind: moduleCRKind, APIVersion: moduleCRAPIVersion}, } if module.Template.Annotations[shared.IsClusterScopedAnnotation] == shared.EnableLabelValue { @@ -279,12 +292,20 @@ func generateModuleStatus(module *common.Module, existStatus *v1beta2.ModuleStat Channel: module.Template.Spec.Channel, Version: manifestObject.Spec.Version, Manifest: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMetaFromObject(manifestObject), - TypeMeta: apimetav1.TypeMeta{Kind: manifestKind, APIVersion: manifestAPIVersion}, + PartialMeta: v1beta2.PartialMeta{ + Name: manifestObject.GetName(), + Namespace: manifestObject.GetNamespace(), + Generation: manifestObject.GetGeneration(), + }, + TypeMeta: apimetav1.TypeMeta{Kind: manifestKind, APIVersion: manifestAPIVersion}, }, Template: &v1beta2.TrackingObject{ - PartialMeta: v1beta2.PartialMetaFromObject(module.Template), - TypeMeta: apimetav1.TypeMeta{Kind: templateKind, APIVersion: templateAPIVersion}, + PartialMeta: v1beta2.PartialMeta{ + Name: module.Template.GetName(), + Namespace: module.Template.GetNamespace(), + Generation: module.Template.GetGeneration(), + }, + TypeMeta: apimetav1.TypeMeta{Kind: templateKind, APIVersion: templateAPIVersion}, }, Resource: moduleResource, } diff --git a/pkg/module/sync/runner_test.go b/pkg/module/sync/runner_test.go index e5754b6680..2784c3de95 100644 --- a/pkg/module/sync/runner_test.go +++ b/pkg/module/sync/runner_test.go @@ -191,10 +191,13 @@ func configureModuleInKyma( func TestNeedToUpdate(t *testing.T) { type args struct { - manifestInCluster *v1beta2.Manifest - manifestObj *v1beta2.Manifest - moduleStatus *v1beta2.ModuleStatus + manifestInCluster *v1beta2.Manifest + manifestObj *v1beta2.Manifest + moduleStatus *v1beta2.ModuleStatus + templateGeneration int64 } + const trackedModuleTemplateGeneration = 1 + const updatedModuleTemplateGeneration = 2 tests := []struct { name string args args @@ -202,7 +205,7 @@ func TestNeedToUpdate(t *testing.T) { }{ { "When manifest in cluster is nil, expect need to update", - args{nil, &v1beta2.Manifest{}, &v1beta2.ModuleStatus{}}, + args{nil, &v1beta2.Manifest{}, &v1beta2.ModuleStatus{}, trackedModuleTemplateGeneration}, true, }, { @@ -214,7 +217,17 @@ func TestNeedToUpdate(t *testing.T) { Labels: map[string]string{shared.ChannelLabel: "regular"}, }, Spec: v1beta2.ManifestSpec{Version: "0.2"}, - }, &v1beta2.ModuleStatus{Version: "0.1", Channel: "regular"}, + }, + &v1beta2.ModuleStatus{ + Version: "0.1", + Channel: "regular", + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: trackedModuleTemplateGeneration, + }, + }, + }, + trackedModuleTemplateGeneration, }, true, }, @@ -227,18 +240,33 @@ func TestNeedToUpdate(t *testing.T) { Labels: map[string]string{shared.ChannelLabel: "fast"}, }, Spec: v1beta2.ManifestSpec{Version: "0.1"}, - }, &v1beta2.ModuleStatus{Version: "0.1", Channel: "regular"}, + }, &v1beta2.ModuleStatus{ + Version: "0.1", Channel: "regular", Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: trackedModuleTemplateGeneration, + }, + }, + }, + trackedModuleTemplateGeneration, }, true, }, { "When cluster Manifest in divergent state, expect need to update", args{ - &v1beta2.Manifest{Status: shared.Status{ - State: "Warning", - }}, + &v1beta2.Manifest{ + Status: shared.Status{ + State: "Warning", + }, + }, &v1beta2.Manifest{}, - &v1beta2.ModuleStatus{State: "Ready"}, + &v1beta2.ModuleStatus{ + State: "Ready", Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: trackedModuleTemplateGeneration, + }, + }, + }, trackedModuleTemplateGeneration, }, true, }, @@ -257,14 +285,48 @@ func TestNeedToUpdate(t *testing.T) { }, Spec: v1beta2.ManifestSpec{Version: "0.1"}, }, - &v1beta2.ModuleStatus{State: "Ready", Version: "0.1", Channel: "regular"}, + &v1beta2.ModuleStatus{ + State: "Ready", Version: "0.1", Channel: "regular", Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: trackedModuleTemplateGeneration, + }, + }, + }, trackedModuleTemplateGeneration, }, false, }, + { + "When moduleTemplate Generation updated, expect update", + args{ + &v1beta2.Manifest{ + Status: shared.Status{ + State: "Ready", + }, + Spec: v1beta2.ManifestSpec{Version: "0.1"}, + }, + &v1beta2.Manifest{ + ObjectMeta: apimetav1.ObjectMeta{ + Labels: map[string]string{shared.ChannelLabel: "regular"}, + }, + Spec: v1beta2.ManifestSpec{Version: "0.1"}, + }, + &v1beta2.ModuleStatus{ + State: "Ready", Version: "0.1", Channel: "regular", Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: trackedModuleTemplateGeneration, + }, + }, + }, updatedModuleTemplateGeneration, + }, + true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, sync.NeedToUpdate(tt.args.manifestInCluster, tt.args.manifestObj, tt.args.moduleStatus), "needToUpdate(%v, %v, %v)", tt.args.manifestInCluster, tt.args.manifestObj, tt.args.moduleStatus) + assert.Equalf(t, tt.want, sync.NeedToUpdate(tt.args.manifestInCluster, tt.args.manifestObj, + tt.args.moduleStatus, tt.args.templateGeneration), "needToUpdate(%v, %v, %v)", + tt.args.manifestInCluster, tt.args.manifestObj, + tt.args.moduleStatus) }) } } diff --git a/pkg/queue/requeue_intervals.go b/pkg/queue/requeue_intervals.go index 1b91a78a92..1eeb8d77e7 100644 --- a/pkg/queue/requeue_intervals.go +++ b/pkg/queue/requeue_intervals.go @@ -18,13 +18,13 @@ func DetermineRequeueInterval(state shared.State, intervals RequeueIntervals) ti case shared.StateError: return intervals.Error case shared.StateDeleting: - fallthrough + return intervals.Busy case shared.StateProcessing: return intervals.Busy - case shared.StateReady: - fallthrough case shared.StateWarning: return intervals.Warning + case shared.StateReady: + return intervals.Success default: return intervals.Success } diff --git a/pkg/templatelookup/regular.go b/pkg/templatelookup/regular.go index fc8c0221dc..53a5c99610 100644 --- a/pkg/templatelookup/regular.go +++ b/pkg/templatelookup/regular.go @@ -51,54 +51,56 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2. if found { continue } - template := t.GetAndValidate(ctx, module.Name, module.Channel, kyma.Spec.Channel) - if template.Err != nil { - templates[module.Name] = &template + templateInfo := t.GetAndValidate(ctx, module.Name, module.Channel, kyma.Spec.Channel) + templateInfo = ValidateTemplateMode(templateInfo, kyma) + if templateInfo.Err != nil { + templates[module.Name] = &templateInfo continue } - if err := t.descriptorProvider.Add(template.ModuleTemplate); err != nil { - template.Err = fmt.Errorf("failed to get descriptor: %w", err) - } - - templates[module.Name] = &template - } - - for moduleName, moduleTemplate := range templates { - if moduleTemplate.Err != nil { + if err := t.descriptorProvider.Add(templateInfo.ModuleTemplate); err != nil { + templateInfo.Err = fmt.Errorf("failed to get descriptor: %w", err) + templates[module.Name] = &templateInfo continue } - - if moduleTemplate.IsInternal() && !kyma.IsInternal() { - moduleTemplate.Err = fmt.Errorf("%w: internal module", ErrTemplateNotAllowed) - templates[moduleName] = moduleTemplate - } - if moduleTemplate.IsBeta() && !kyma.IsBeta() { - moduleTemplate.Err = fmt.Errorf("%w: beta module", ErrTemplateNotAllowed) - templates[moduleName] = moduleTemplate - } - } - - for moduleName, moduleTemplate := range templates { - template := moduleTemplate for i := range kyma.Status.Modules { moduleStatus := &kyma.Status.Modules[i] - if moduleMatch(moduleStatus, moduleName) && template.ModuleTemplate != nil { - t.checkValidTemplateUpdate(ctx, template, moduleStatus) + if moduleMatch(moduleStatus, module.Name) { + descriptor, err := t.descriptorProvider.GetDescriptor(templateInfo.ModuleTemplate) + if err != nil { + msg := "could not handle channel skew as descriptor from template cannot be fetched" + templateInfo.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) + continue + } + markInvalidChannelSkewUpdate(ctx, &templateInfo, moduleStatus, descriptor.Version) } } - templates[moduleName] = template + templates[module.Name] = &templateInfo } - return templates } +func ValidateTemplateMode(template ModuleTemplateInfo, kyma *v1beta2.Kyma) ModuleTemplateInfo { + if template.Err != nil { + return template + } + if template.IsInternal() && !kyma.IsInternal() { + template.Err = fmt.Errorf("%w: internal module", ErrTemplateNotAllowed) + return template + } + if template.IsBeta() && !kyma.IsBeta() { + template.Err = fmt.Errorf("%w: beta module", ErrTemplateNotAllowed) + return template + } + return template +} + func (t *TemplateLookup) GetAndValidate(ctx context.Context, name, channel, defaultChannel string) ModuleTemplateInfo { desiredChannel := getDesiredChannel(channel, defaultChannel) info := ModuleTemplateInfo{ DesiredChannel: desiredChannel, } - template, err := t.getTemplate(ctx, t, name, desiredChannel) + template, err := t.getTemplate(ctx, name, desiredChannel) if err != nil { info.Err = err return info @@ -138,88 +140,70 @@ func logUsedChannel(ctx context.Context, name string, actualChannel string, defa } func moduleMatch(moduleStatus *v1beta2.ModuleStatus, moduleName string) bool { - return moduleStatus.FQDN == moduleName || moduleStatus.Name == moduleName + return moduleStatus.Name == moduleName } -// checkValidTemplateUpdate verifies if the given ModuleTemplate is valid for update and sets their IsValidUpdate Flag -// based on provided Modules, provided by the Cluster as a status of the last known module state. -// It does this by looking into selected key properties: -// 1. If the generation of ModuleTemplate changes, it means the spec is outdated -// 2. If the channel of ModuleTemplate changes, it means the kyma has an old reference to a previous channel. -func (t *TemplateLookup) checkValidTemplateUpdate( - ctx context.Context, moduleTemplate *ModuleTemplateInfo, moduleStatus *v1beta2.ModuleStatus, +// markInvalidChannelSkewUpdate verifies if the given ModuleTemplate is invalid for update when channel switch is detected. +func markInvalidChannelSkewUpdate(ctx context.Context, moduleTemplateInfo *ModuleTemplateInfo, + moduleStatus *v1beta2.ModuleStatus, templateVersion string, ) { if moduleStatus.Template == nil { return } + if moduleTemplateInfo == nil || moduleTemplateInfo.Err != nil { + return + } + logger := logf.FromContext(ctx) checkLog := logger.WithValues("module", moduleStatus.FQDN, - "template", moduleTemplate.Name, - "newTemplateGeneration", moduleTemplate.GetGeneration(), - "previousTemplateGeneration", moduleStatus.Template.Generation, - "newTemplateChannel", moduleTemplate.Spec.Channel, + "template", moduleTemplateInfo.Name, + "newTemplateGeneration", moduleTemplateInfo.GetGeneration(), + "previousTemplateGeneration", moduleStatus.Template.GetGeneration(), + "newTemplateChannel", moduleTemplateInfo.Spec.Channel, "previousTemplateChannel", moduleStatus.Channel, ) - if moduleTemplate.Spec.Channel != moduleStatus.Channel { - checkLog.Info("outdated ModuleTemplate: channel skew") - - descriptor, err := t.descriptorProvider.GetDescriptor(moduleTemplate.ModuleTemplate) - if err != nil { - msg := "could not handle channel skew as descriptor from template cannot be fetched" - checkLog.Error(err, msg) - moduleTemplate.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) - return - } - - versionInTemplate, err := semver.NewVersion(descriptor.Version) - if err != nil { - msg := "could not handle channel skew as descriptor from template contains invalid version" - checkLog.Error(err, msg) - moduleTemplate.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) - return - } - - versionInStatus, err := semver.NewVersion(moduleStatus.Version) - if err != nil { - msg := "could not handle channel skew as Modules contains invalid version" - checkLog.Error(err, msg) - moduleTemplate.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) - return - } - - checkLog = checkLog.WithValues( - "previousVersion", versionInTemplate.String(), - "newVersion", versionInStatus.String(), - ) + if moduleTemplateInfo.Spec.Channel == moduleStatus.Channel { + return + } - // channel skews have to be handled with more detail. If a channel is changed this means - // that the downstream kyma might have changed its target channel for the module, meaning - // the old moduleStatus is reflecting the previous desired state. - // when increasing channel stability, this means we could potentially have a downgrade - // of module versions here (fast: v2.0.0 get downgraded to regular: v1.0.0). In this - // case we want to suspend updating the module until we reach v2.0.0 in regular, since downgrades - // are not supported. To circumvent this, a module can be uninstalled and then reinstalled in the old channel. - if !v1beta2.IsValidVersionChange(versionInTemplate, versionInStatus) { - msg := fmt.Sprintf("ignore channel skew (from %s to %s), "+ - "as a higher version (%s) of the module was previously installed", - moduleStatus.Channel, moduleTemplate.Spec.Channel, versionInStatus.String()) - checkLog.Info(msg) - moduleTemplate.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) - return - } + checkLog.Info("outdated ModuleTemplate: channel skew") + versionInTemplate, err := semver.NewVersion(templateVersion) + if err != nil { + msg := "could not handle channel skew as descriptor from template contains invalid version" + checkLog.Error(err, msg) + moduleTemplateInfo.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) return } - // generation skews always have to be handled. We are not in need of checking downgrades here, - // since these are caught by our validating webhook. We do not support downgrades of Versions - // in ModuleTemplates, meaning the only way the generation can be changed is by changing the target - // channel (valid change) or a version increase - if moduleTemplate.GetGeneration() != moduleStatus.Template.Generation { - checkLog.Info("outdated ModuleTemplate: generation skew") + versionInStatus, err := semver.NewVersion(moduleStatus.Version) + if err != nil { + msg := "could not handle channel skew as Modules contains invalid version" + checkLog.Error(err, msg) + moduleTemplateInfo.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) return } + + checkLog = checkLog.WithValues( + "previousVersion", versionInTemplate.String(), + "newVersion", versionInStatus.String(), + ) + + // channel skews have to be handled with more detail. If a channel is changed this means + // that the downstream kyma might have changed its target channel for the module, meaning + // the old moduleStatus is reflecting the previous desired state. + // when increasing channel stability, this means we could potentially have a downgrade + // of module versions here (fast: v2.0.0 get downgraded to regular: v1.0.0). In this + // case we want to suspend updating the module until we reach v2.0.0 in regular, since downgrades + // are not supported. To circumvent this, a module can be uninstalled and then reinstalled in the old channel. + if !v1beta2.IsValidVersionChange(versionInTemplate, versionInStatus) { + msg := fmt.Sprintf("ignore channel skew (from %s to %s), "+ + "as a higher version (%s) of the module was previously installed", + moduleStatus.Channel, moduleTemplateInfo.Spec.Channel, versionInStatus.String()) + checkLog.Info(msg) + moduleTemplateInfo.Err = fmt.Errorf("%w: %s", ErrTemplateUpdateNotAllowed, msg) + } } func getDesiredChannel(moduleChannel, globalChannel string) string { @@ -237,39 +221,22 @@ func getDesiredChannel(moduleChannel, globalChannel string) string { return desiredChannel } -func (t *TemplateLookup) getTemplate(ctx context.Context, clnt client.Reader, name, desiredChannel string) ( +func (t *TemplateLookup) getTemplate(ctx context.Context, name, desiredChannel string) ( *v1beta2.ModuleTemplate, error, ) { templateList := &v1beta2.ModuleTemplateList{} - err := clnt.List(ctx, templateList) + 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 { - template := template // capture unique address + template := template if template.Labels[shared.ModuleName] == name && template.Spec.Channel == desiredChannel { filteredTemplates = append(filteredTemplates, &template) continue } - if fmt.Sprintf("%s/%s", template.Namespace, template.Name) == name && - template.Spec.Channel == desiredChannel { - filteredTemplates = append(filteredTemplates, &template) - continue - } - if template.ObjectMeta.Name == name && template.Spec.Channel == desiredChannel { - filteredTemplates = append(filteredTemplates, &template) - continue - } - descriptor, err := t.descriptorProvider.GetDescriptor(&template) - if err != nil { - return nil, fmt.Errorf("invalid ModuleTemplate descriptor: %w", err) - } - if descriptor.Name == name && template.Spec.Channel == desiredChannel { - filteredTemplates = append(filteredTemplates, &template) - continue - } } if len(filteredTemplates) > 1 { diff --git a/pkg/templatelookup/regular_test.go b/pkg/templatelookup/regular_test.go new file mode 100644 index 0000000000..03170c4310 --- /dev/null +++ b/pkg/templatelookup/regular_test.go @@ -0,0 +1,380 @@ +package templatelookup_test + +import ( + "context" + "errors" + "testing" + + "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc" + ocmmetav1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1" + compdescv2 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/versions/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/pkg/testutils" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" +) + +type FakeModuleTemplateReader struct { + templateList v1beta2.ModuleTemplateList +} + +func NewFakeModuleTemplateReader(templateList v1beta2.ModuleTemplateList) *FakeModuleTemplateReader { + return &FakeModuleTemplateReader{ + templateList: templateList, + } +} + +func (f *FakeModuleTemplateReader) List(_ context.Context, list client.ObjectList, _ ...client.ListOption) error { + castedList, ok := list.(*v1beta2.ModuleTemplateList) + if !ok { + return errors.New("list is not of type *v1beta2.ModuleTemplateList") + } + castedList.Items = append(castedList.Items, f.templateList.Items...) + return nil +} + +func (f *FakeModuleTemplateReader) Get(_ context.Context, _ client.ObjectKey, _ client.Object, + _ ...client.GetOption, +) error { + return nil +} + +func TestValidateTemplateMode(t *testing.T) { + tests := []struct { + name string + template templatelookup.ModuleTemplateInfo + kyma *v1beta2.Kyma + wantErr error + }{ + { + name: "When TemplateInfo contains Error, Then the output is same as input", + template: templatelookup.ModuleTemplateInfo{ + Err: templatelookup.ErrTemplateNotAllowed, + }, + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + { + name: "When ModuleTemplate is internal but Kyma is not, Then result contains error", + template: templatelookup.ModuleTemplateInfo{ + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithLabel(shared.InternalLabel, "true").Build(), + }, + kyma: builder.NewKymaBuilder(). + WithLabel(shared.InternalLabel, "false"). + Build(), + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + { + name: "When ModuleTemplate is beta but Kyma is not, Then result contains error", + template: templatelookup.ModuleTemplateInfo{ + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithLabel(shared.BetaLabel, "true").Build(), + }, + kyma: builder.NewKymaBuilder(). + WithLabel(shared.BetaLabel, "false"). + Build(), + wantErr: templatelookup.ErrTemplateNotAllowed, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + if got := templatelookup.ValidateTemplateMode(testCase.template, testCase.kyma); !errors.Is(got.Err, + testCase.wantErr) { + t.Errorf("ValidateTemplateMode() = %v, want %v", got, testCase.wantErr) + } + }) + } +} + +func TestTemplateLookup_GetRegularTemplates_WhenSwitchModuleChannel(t *testing.T) { + testModule := testutils.NewTestModule("module1", "new_channel") + + tests := []struct { + name string + kyma *v1beta2.Kyma + availableModuleTemplate v1beta2.ModuleTemplateList + want templatelookup.ModuleTemplatesByModuleName + }{ + { + name: "When upgrade version during channel switch, Then result contains no error", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule). + WithModuleStatus(v1beta2.ModuleStatus{ + Name: testModule.Name, + Channel: v1beta2.DefaultChannel, + Version: "1.0.0", + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: 1, + }, + }, + }).Build(), + availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, testModule.Channel, "1.1.0"), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: nil, + }, + }, + }, { + name: "When downgrade version during channel switch, Then result contains error", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule). + WithModuleStatus(v1beta2.ModuleStatus{ + Name: testModule.Name, + Channel: v1beta2.DefaultChannel, + Version: "1.1.0", + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: 1, + }, + }, + }).Build(), + availableModuleTemplate: generateModuleTemplateListWithModule(testModule.Name, testModule.Channel, "1.0.0"), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: templatelookup.ErrTemplateUpdateNotAllowed, + }, + }, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(testCase.availableModuleTemplate), + provider.NewCachedDescriptorProvider()) + got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) + assert.Equal(t, len(got), len(testCase.want)) + for key, module := range got { + wantModule, ok := testCase.want[key] + assert.True(t, ok) + assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) + require.ErrorIs(t, module.Err, wantModule.Err) + } + }) + } +} + +func generateModuleTemplateListWithModule(moduleName, moduleChannel, moduleVersion string) v1beta2.ModuleTemplateList { + templateList := v1beta2.ModuleTemplateList{} + templateList.Items = append(templateList.Items, *builder.NewModuleTemplateBuilder(). + WithModuleName(moduleName). + WithChannel(moduleChannel). + WithDescriptor(&v1beta2.Descriptor{ + ComponentDescriptor: &compdesc.ComponentDescriptor{ + Metadata: compdesc.Metadata{ + ConfiguredVersion: compdescv2.SchemaVersion, + }, + ComponentSpec: compdesc.ComponentSpec{ + ObjectMeta: ocmmetav1.ObjectMeta{ + Version: moduleVersion, + }, + }, + }, + }).Build()) + return templateList +} + +func TestNewTemplateLookup_GetRegularTemplates_WhenModuleTemplateContainsInvalidDescriptor(t *testing.T) { + testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) + + tests := []struct { + name string + kyma *v1beta2.Kyma + want templatelookup.ModuleTemplatesByModuleName + }{ + { + name: "When module enabled in Spec, then return ModuleTemplatesByModuleName with error", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: provider.ErrDecode, + }, + }, + }, + { + name: "When module exits in ModuleStatus only, then return ModuleTemplatesByModuleName with error", + kyma: builder.NewKymaBuilder(). + WithModuleStatus(v1beta2.ModuleStatus{ + Name: testModule.Name, + Channel: testModule.Channel, + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: 1, + }, + }, + }).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: provider.ErrDecode, + }, + }, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + givenTemplateList := &v1beta2.ModuleTemplateList{} + for _, module := range testCase.kyma.GetAvailableModules() { + givenTemplateList.Items = append(givenTemplateList.Items, *builder.NewModuleTemplateBuilder(). + WithModuleName(module.Name). + WithChannel(module.Channel). + WithDescriptor(nil). + WithRawDescriptor([]byte("{invalid_json}")).Build()) + } + lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList), + provider.NewCachedDescriptorProvider()) + got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) + assert.Equal(t, len(got), len(testCase.want)) + for key, module := range got { + wantModule, ok := testCase.want[key] + assert.True(t, ok) + assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) + require.ErrorIs(t, module.Err, wantModule.Err) + } + }) + } +} + +func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateNotFound(t *testing.T) { + testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) + + tests := []struct { + name string + kyma *v1beta2.Kyma + want templatelookup.ModuleTemplatesByModuleName + }{ + { + name: "When no module enabled in Spec, then return empty ModuleTemplatesByModuleName", + kyma: builder.NewKymaBuilder().Build(), + want: templatelookup.ModuleTemplatesByModuleName{}, + }, + { + name: "When module enabled in Spec, then return ModuleTemplatesByModuleName with error", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: templatelookup.ErrNoTemplatesInListResult, + }, + }, + }, + { + name: "When module exits in ModuleStatus only, then return ModuleTemplatesByModuleName with error", + kyma: builder.NewKymaBuilder(). + WithModuleStatus(v1beta2.ModuleStatus{ + Name: testModule.Name, + Channel: testModule.Channel, + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: 1, + }, + }, + }).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: templatelookup.ErrNoTemplatesInListResult, + }, + }, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + givenTemplateList := &v1beta2.ModuleTemplateList{} + lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList), + provider.NewCachedDescriptorProvider()) + got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) + assert.Equal(t, len(got), len(testCase.want)) + for key, module := range got { + wantModule, ok := testCase.want[key] + assert.True(t, ok) + assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) + require.ErrorIs(t, module.Err, wantModule.Err) + assert.Nil(t, module.ModuleTemplate) + } + }) + } +} + +func TestTemplateLookup_GetRegularTemplates_WhenModuleTemplateExists(t *testing.T) { + testModule := testutils.NewTestModule("module1", v1beta2.DefaultChannel) + + tests := []struct { + name string + kyma *v1beta2.Kyma + want templatelookup.ModuleTemplatesByModuleName + }{ + { + name: "When module enabled in Spec, then return expected moduleTemplateInfo", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: nil, + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithModuleName(testModule.Name). + WithChannel(testModule.Channel). + Build(), + }, + }, + }, + { + name: "When module exits in ModuleStatus only, then return expected moduleTemplateInfo", + kyma: builder.NewKymaBuilder(). + WithEnabledModule(testModule). + WithModuleStatus(v1beta2.ModuleStatus{ + Name: testModule.Name, + Channel: testModule.Channel, + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Generation: 1, + }, + }, + }).Build(), + want: templatelookup.ModuleTemplatesByModuleName{ + testModule.Name: &templatelookup.ModuleTemplateInfo{ + DesiredChannel: testModule.Channel, + Err: nil, + ModuleTemplate: builder.NewModuleTemplateBuilder(). + WithModuleName(testModule.Name). + WithChannel(testModule.Channel). + Build(), + }, + }, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + givenTemplateList := &v1beta2.ModuleTemplateList{} + for _, module := range testCase.kyma.GetAvailableModules() { + givenTemplateList.Items = append(givenTemplateList.Items, *builder.NewModuleTemplateBuilder(). + WithModuleName(module.Name). + WithChannel(module.Channel). + WithOCM(compdescv2.SchemaVersion).Build()) + } + lookup := templatelookup.NewTemplateLookup(NewFakeModuleTemplateReader(*givenTemplateList), + provider.NewCachedDescriptorProvider()) + got := lookup.GetRegularTemplates(context.TODO(), testCase.kyma) + assert.Equal(t, len(got), len(testCase.want)) + for key, module := range got { + wantModule, ok := testCase.want[key] + assert.True(t, ok) + assert.Equal(t, wantModule.DesiredChannel, module.DesiredChannel) + require.ErrorIs(t, module.Err, wantModule.Err) + assert.Equal(t, wantModule.ModuleTemplate.Spec.Channel, module.ModuleTemplate.Spec.Channel) + } + }) + } +} diff --git a/pkg/testutils/builder/kyma.go b/pkg/testutils/builder/kyma.go index f6bb68c86a..dadf252081 100644 --- a/pkg/testutils/builder/kyma.go +++ b/pkg/testutils/builder/kyma.go @@ -38,6 +38,15 @@ func (kb KymaBuilder) WithName(name string) KymaBuilder { return kb } +// WithEnabledModule append module to v1beta2.Kyma.Spec.Modules. +func (kb KymaBuilder) WithEnabledModule(module v1beta2.Module) KymaBuilder { + if kb.kyma.Spec.Modules == nil { + kb.kyma.Spec.Modules = []v1beta2.Module{} + } + kb.kyma.Spec.Modules = append(kb.kyma.Spec.Modules, module) + return kb +} + // WithNamePrefix sets v1beta2.Kyma.ObjectMeta.Name. func (kb KymaBuilder) WithNamePrefix(prefix string) KymaBuilder { kb.kyma.ObjectMeta.Name = fmt.Sprintf("%s-%s", prefix, random.Name()) @@ -83,6 +92,15 @@ func (kb KymaBuilder) WithCondition(condition apimetav1.Condition) KymaBuilder { return kb } +// WithCondition adds a ModuleStatus to v1beta2.Kyma.Status.Modules. +func (kb KymaBuilder) WithModuleStatus(moduleStatus v1beta2.ModuleStatus) KymaBuilder { + if kb.kyma.Status.Modules == nil { + kb.kyma.Status.Modules = []v1beta2.ModuleStatus{} + } + kb.kyma.Status.Modules = append(kb.kyma.Status.Modules, moduleStatus) + return kb +} + // Build returns the built v1beta2.Kyma. func (kb KymaBuilder) Build() *v1beta2.Kyma { return kb.kyma diff --git a/pkg/testutils/builder/moduletemplate.go b/pkg/testutils/builder/moduletemplate.go index f7904e3248..4858da3c63 100644 --- a/pkg/testutils/builder/moduletemplate.go +++ b/pkg/testutils/builder/moduletemplate.go @@ -29,7 +29,7 @@ func NewModuleTemplateBuilder() ModuleTemplateBuilder { moduleTemplate: &v1beta2.ModuleTemplate{ TypeMeta: apimetav1.TypeMeta{ APIVersion: v1beta2.GroupVersion.String(), - Kind: string(shared.KymaKind), + Kind: string(shared.ModuleTemplateKind), }, ObjectMeta: apimetav1.ObjectMeta{ Name: random.Name(), @@ -39,9 +39,11 @@ func NewModuleTemplateBuilder() ModuleTemplateBuilder { Data: data, Descriptor: machineryruntime.RawExtension{ Object: &v1beta2.Descriptor{ - ComponentDescriptor: &compdesc.ComponentDescriptor{Metadata: compdesc.Metadata{ - ConfiguredVersion: compdescv2.SchemaVersion, - }}, + ComponentDescriptor: &compdesc.ComponentDescriptor{ + Metadata: compdesc.Metadata{ + ConfiguredVersion: compdescv2.SchemaVersion, + }, + }, }, }, }, diff --git a/pkg/testutils/kyma.go b/pkg/testutils/kyma.go index 889de1f954..2a39eb5175 100644 --- a/pkg/testutils/kyma.go +++ b/pkg/testutils/kyma.go @@ -139,6 +139,11 @@ func EnableModule(ctx context.Context, if err != nil { return err } + for _, enabledModule := range kyma.Spec.Modules { + if enabledModule.Name == module.Name { + return nil + } + } kyma.Spec.Modules = append( kyma.Spec.Modules, module) err = clnt.Update(ctx, kyma) diff --git a/pkg/testutils/moduletemplate.go b/pkg/testutils/moduletemplate.go index 91f82fea18..b820dc36f9 100644 --- a/pkg/testutils/moduletemplate.go +++ b/pkg/testutils/moduletemplate.go @@ -18,7 +18,7 @@ func GetModuleTemplate(ctx context.Context, module v1beta2.Module, defaultChannel string, ) (*v1beta2.ModuleTemplate, error) { - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() templateLookup := templatelookup.NewTemplateLookup(clnt, descriptorProvider) templateInfo := templateLookup.GetAndValidate(ctx, module.Name, module.Channel, defaultChannel) if templateInfo.Err != nil { @@ -94,7 +94,7 @@ func ReadModuleVersionFromModuleTemplate(ctx context.Context, clnt client.Client return "", fmt.Errorf("failed to fetch ModuleTemplate: %w", err) } - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() ocmDesc, err := descriptorProvider.GetDescriptor(moduleTemplate) if err != nil { return "", fmt.Errorf("failed to get descriptor: %w", err) diff --git a/sec-scanners-config.yaml b/sec-scanners-config.yaml index 958ea56d8b..973ad4bec0 100644 --- a/sec-scanners-config.yaml +++ b/sec-scanners-config.yaml @@ -1,7 +1,7 @@ module-name: lifecycle-manager protecode: - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:latest - - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:1.0.0 + - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:1.1.0 whitesource: language: golang-mod exclude: diff --git a/tests/integration/apiwebhook/moduletemplate_crd_validation_test.go b/tests/integration/apiwebhook/moduletemplate_crd_validation_test.go index 90d29e25de..843c13ab3c 100644 --- a/tests/integration/apiwebhook/moduletemplate_crd_validation_test.go +++ b/tests/integration/apiwebhook/moduletemplate_crd_validation_test.go @@ -77,7 +77,7 @@ var _ = Describe("Webhook ValidationCreate Strict", Ordered, func() { WithChannel(v1beta2.DefaultChannel). WithOCM(compdescv2.SchemaVersion).Build() Expect(k8sClient.Create(webhookServerContext, template)).Should(Succeed()) - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() descriptor, err := descriptorProvider.GetDescriptor(template) Expect(err).ToNot(HaveOccurred()) version, err := semver.NewVersion(descriptor.Version) diff --git a/tests/integration/controller/eventfilters/suite_test.go b/tests/integration/controller/eventfilters/suite_test.go index a249b7a928..cb2628c55e 100644 --- a/tests/integration/controller/eventfilters/suite_test.go +++ b/tests/integration/controller/eventfilters/suite_test.go @@ -34,6 +34,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kyma-project/lifecycle-manager/api" "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/internal" @@ -47,7 +49,6 @@ import ( "github.com/kyma-project/lifecycle-manager/pkg/queue" testskrcontext "github.com/kyma-project/lifecycle-manager/pkg/testutils/skrcontextimpl" "github.com/kyma-project/lifecycle-manager/tests/integration" - "sigs.k8s.io/controller-runtime/pkg/client" _ "github.com/open-component-model/ocm/pkg/contexts/ocm" @@ -142,7 +143,7 @@ var _ = BeforeSuite(func() { SkrContextFactory: testSkrContextFactory, Event: testEventRec, RequeueIntervals: intervals, - DescriptorProvider: provider.NewCachedDescriptorProvider(nil), + DescriptorProvider: provider.NewCachedDescriptorProvider(), SyncRemoteCrds: remote.NewSyncCrdsUseCase(kcpClient, testSkrContextFactory, nil), InKCPMode: false, RemoteSyncNamespace: flags.DefaultRemoteSyncNamespace, diff --git a/tests/integration/controller/kcp/remote_sync_test.go b/tests/integration/controller/kcp/remote_sync_test.go index 9fca8e7469..788ac42a85 100644 --- a/tests/integration/controller/kcp/remote_sync_test.go +++ b/tests/integration/controller/kcp/remote_sync_test.go @@ -15,9 +15,10 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" - . "github.com/kyma-project/lifecycle-manager/pkg/testutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + . "github.com/kyma-project/lifecycle-manager/pkg/testutils" ) var ( @@ -223,7 +224,7 @@ func buildSkrKyma() *v1beta2.Kyma { func IsDescriptorCached(template *v1beta2.ModuleTemplate) bool { key := cache.GenerateDescriptorKey(template) - result := descriptorCache.Get(key) + result := descriptorProvider.DescriptorCache.Get(key) return result != nil } diff --git a/tests/integration/controller/kcp/suite_test.go b/tests/integration/controller/kcp/suite_test.go index 3b98f072ab..7e1a8d2118 100644 --- a/tests/integration/controller/kcp/suite_test.go +++ b/tests/integration/controller/kcp/suite_test.go @@ -40,7 +40,6 @@ import ( "github.com/kyma-project/lifecycle-manager/internal" "github.com/kyma-project/lifecycle-manager/internal/controller/kyma" "github.com/kyma-project/lifecycle-manager/internal/crd" - "github.com/kyma-project/lifecycle-manager/internal/descriptor/cache" "github.com/kyma-project/lifecycle-manager/internal/descriptor/provider" "github.com/kyma-project/lifecycle-manager/internal/event" "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" @@ -48,12 +47,12 @@ import ( "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/testutils" testskrcontext "github.com/kyma-project/lifecycle-manager/pkg/testutils/skrcontextimpl" "github.com/kyma-project/lifecycle-manager/tests/integration" _ "github.com/open-component-model/ocm/pkg/contexts/ocm" - . "github.com/kyma-project/lifecycle-manager/pkg/testutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -71,7 +70,6 @@ var ( ctx context.Context cancel context.CancelFunc cfg *rest.Config - descriptorCache *cache.DescriptorCache descriptorProvider *provider.CachedDescriptorProvider crdCache *crd.Cache ) @@ -88,7 +86,7 @@ var _ = BeforeSuite(func() { var err error By("bootstrapping test environment") - externalCRDs, err := AppendExternalCRDs( + externalCRDs, err := testutils.AppendExternalCRDs( filepath.Join(integration.GetProjectRoot(), "config", "samples", "tests", "crds"), "cert-manager-v1.10.1.crds.yaml", "istio-v1.17.1.crds.yaml") @@ -140,8 +138,7 @@ var _ = BeforeSuite(func() { testEventRec := event.NewRecorderWrapper(mgr.GetEventRecorderFor(shared.OperatorName)) testSkrContextFactory = testskrcontext.NewDualClusterFactory(kcpClient.Scheme(), testEventRec) - descriptorCache = cache.NewDescriptorCache() - descriptorProvider = provider.NewCachedDescriptorProvider(descriptorCache) + descriptorProvider = provider.NewCachedDescriptorProvider() crdCache = crd.NewCache(nil) err = (&kyma.Reconciler{ Client: kcpClient, diff --git a/tests/integration/controller/kyma/manifest_test.go b/tests/integration/controller/kyma/manifest_test.go index 01621d4d07..1c6bc56ffa 100644 --- a/tests/integration/controller/kyma/manifest_test.go +++ b/tests/integration/controller/kyma/manifest_test.go @@ -18,15 +18,15 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" . "github.com/kyma-project/lifecycle-manager/pkg/testutils" - "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) const ( @@ -329,6 +329,42 @@ var _ = Describe("Test Reconciliation Skip label for Manifest", Ordered, func() }) }) +var _ = Describe("Modules can only be referenced via module name", Ordered, func() { + kyma := NewTestKyma("random-kyma") + + moduleReferencedWithLabel := NewTestModuleWithFixName("random-module", v1beta2.DefaultChannel) + moduleReferencedWithNamespacedName := NewTestModuleWithFixName( + v1beta2.DefaultChannel+shared.Separator+"random-module", v1beta2.DefaultChannel) + moduleReferencedWithFQDN := NewTestModuleWithFixName("kyma-project.io/module/"+"random-module", v1beta2.DefaultChannel) + + kyma.Spec.Modules = append(kyma.Spec.Modules, moduleReferencedWithLabel) + RegisterDefaultLifecycleForKyma(kyma) + + Context("When operator is referenced just by the label name", func() { + It("returns the expected operator", func() { + moduleTemplate, err := GetModuleTemplate(ctx, kcpClient, moduleReferencedWithLabel, kyma.Spec.Channel) + Expect(err).ToNot(HaveOccurred()) + + foundModuleName := moduleTemplate.Labels[shared.ModuleName] + Expect(foundModuleName).To(Equal(moduleReferencedWithLabel.Name)) + }) + }) + + Context("When operator is referenced by Namespace/Name", func() { + It("cannot find the operator", func() { + _, err := GetModuleTemplate(ctx, kcpClient, moduleReferencedWithNamespacedName, kyma.Spec.Channel) + Expect(err.Error()).Should(ContainSubstring(templatelookup.ErrNoTemplatesInListResult.Error())) + }) + }) + + Context("When operator is referenced by FQDN", func() { + It("cannot find the operator", func() { + _, err := GetModuleTemplate(ctx, kcpClient, moduleReferencedWithFQDN, kyma.Spec.Channel) + Expect(err.Error()).Should(ContainSubstring(templatelookup.ErrNoTemplatesInListResult.Error())) + }) + }) +}) + func findRawManifestResource(reslist []compdesc.Resource) *compdesc.Resource { for _, r := range reslist { if r.Name == v1beta2.RawManifestLayerName { diff --git a/tests/integration/controller/kyma/suite_test.go b/tests/integration/controller/kyma/suite_test.go index 5920854b7b..5d110d07d9 100644 --- a/tests/integration/controller/kyma/suite_test.go +++ b/tests/integration/controller/kyma/suite_test.go @@ -130,7 +130,7 @@ var _ = BeforeSuite(func() { Warning: 100 * time.Millisecond, } - descriptorProvider = provider.NewCachedDescriptorProvider(nil) + descriptorProvider = provider.NewCachedDescriptorProvider() kcpClient = mgr.GetClient() testEventRec := event.NewRecorderWrapper(mgr.GetEventRecorderFor(shared.OperatorName)) testSkrContextFactory := testskrcontext.NewSingleClusterFactory(kcpClient, mgr.GetConfig(), testEventRec) diff --git a/tests/integration/controller/mandatorymodule/deletion/suite_test.go b/tests/integration/controller/mandatorymodule/deletion/suite_test.go index 1795888e62..15163b843f 100644 --- a/tests/integration/controller/mandatorymodule/deletion/suite_test.go +++ b/tests/integration/controller/mandatorymodule/deletion/suite_test.go @@ -115,7 +115,7 @@ var _ = BeforeSuite(func() { Warning: 100 * time.Millisecond, } - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() reconciler = &mandatorymodule.DeletionReconciler{ Client: mgr.GetClient(), Event: event.NewRecorderWrapper(mgr.GetEventRecorderFor(shared.OperatorName)), diff --git a/tests/integration/controller/mandatorymodule/installation/suite_test.go b/tests/integration/controller/mandatorymodule/installation/suite_test.go index 781eea10f0..23240dfd7a 100644 --- a/tests/integration/controller/mandatorymodule/installation/suite_test.go +++ b/tests/integration/controller/mandatorymodule/installation/suite_test.go @@ -106,7 +106,7 @@ var _ = BeforeSuite(func() { Warning: 100 * time.Millisecond, } - descriptorProvider := provider.NewCachedDescriptorProvider(nil) + descriptorProvider := provider.NewCachedDescriptorProvider() reconciler = &mandatorymodule.InstallationReconciler{ Client: mgr.GetClient(), DescriptorProvider: descriptorProvider, 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 39ae7f4576..9c1fcdb5c8 100644 --- a/tests/integration/controller/manifest/custom_resource_check/suite_test.go +++ b/tests/integration/controller/manifest/custom_resource_check/suite_test.go @@ -138,7 +138,9 @@ var _ = BeforeSuite(func() { extractor := manifest.NewPathExtractor(nil) reconciler = declarativev2.NewFromManager(mgr, queue.RequeueIntervals{ Success: 1 * time.Second, + Busy: 1 * time.Second, Error: 1 * time.Second, + Warning: 1 * time.Second, }, metrics.NewManifestMetrics(metrics.NewSharedMetrics()), metrics.NewMandatoryModulesMetrics(), manifest.NewSpecResolver(kcp.Client, extractor), diff --git a/tests/integration/controller/manifest/suite_test.go b/tests/integration/controller/manifest/suite_test.go index f8ce48125e..03aac994ce 100644 --- a/tests/integration/controller/manifest/suite_test.go +++ b/tests/integration/controller/manifest/suite_test.go @@ -134,7 +134,10 @@ var _ = BeforeSuite(func() { kcp := &declarativev2.ClusterInfo{Config: cfg, Client: kcpClient} extractor := manifest.NewPathExtractor(nil) reconciler = declarativev2.NewFromManager(mgr, queue.RequeueIntervals{ - Success: 1 * time.Second, Busy: 1 * time.Second, + Success: 1 * time.Second, + Busy: 1 * time.Second, + Error: 1 * time.Second, + Warning: 1 * time.Second, }, metrics.NewManifestMetrics(metrics.NewSharedMetrics()), metrics.NewMandatoryModulesMetrics(), manifest.NewSpecResolver(kcp.Client, extractor), diff --git a/tests/integration/controller/withwatcher/suite_test.go b/tests/integration/controller/withwatcher/suite_test.go index 65902930a8..3241563bfa 100644 --- a/tests/integration/controller/withwatcher/suite_test.go +++ b/tests/integration/controller/withwatcher/suite_test.go @@ -213,7 +213,7 @@ var _ = BeforeSuite(func() { Event: testEventRec, RequeueIntervals: intervals, SKRWebhookManager: skrWebhookChartManager, - DescriptorProvider: provider.NewCachedDescriptorProvider(nil), + DescriptorProvider: provider.NewCachedDescriptorProvider(), SyncRemoteCrds: remote.NewSyncCrdsUseCase(kcpClient, testSkrContextFactory, nil), RemoteSyncNamespace: flags.DefaultRemoteSyncNamespace, InKCPMode: true, diff --git a/unit-test-coverage.yaml b/unit-test-coverage.yaml index ab5f80c47b..f57b0b809c 100644 --- a/unit-test-coverage.yaml +++ b/unit-test-coverage.yaml @@ -1,9 +1,10 @@ packages: internal/crd: 92 internal/descriptor/cache: 93 - internal/descriptor/provider: 68 + internal/descriptor/provider: 66 internal/event: 100 internal/manifest/filemutex: 100 internal/istio: 63 internal/pkg/resources: 85 internal/remote: 5 + pkg/templatelookup: 63