From c7a0e5f8e60f5aec4e7fbcb618951d72adab75d2 Mon Sep 17 00:00:00 2001 From: Damian Badura <45110612+dbadura@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:12:29 +0200 Subject: [PATCH 01/10] cleanup serverless chart config (#1798) --- internal/deploy/values/builder.go | 38 ----------- internal/deploy/values/values.go | 13 +--- internal/deploy/values/values_test.go | 94 --------------------------- 3 files changed, 1 insertion(+), 144 deletions(-) diff --git a/internal/deploy/values/builder.go b/internal/deploy/values/builder.go index 85c3e50a2..66adfea2c 100644 --- a/internal/deploy/values/builder.go +++ b/internal/deploy/values/builder.go @@ -50,44 +50,6 @@ func (b *builder) addDefaultGlobalTLSCrtAndKey(tlsCrt, tlsKey string) *builder { }) } -type serverlessRegistryConfig struct { - enable bool - serverAddress string - internalServerAddress string - registryAddress string -} - -func (b *builder) addDefaultServerlessRegistryConfig(config serverlessRegistryConfig) *builder { - return b.addDefaultValues(map[string]interface{}{ - "serverless": map[string]interface{}{ - "dockerRegistry": map[string]interface{}{ - "enableInternal": config.enable, - "internalServerAddress": config.internalServerAddress, - "serverAddress": config.serverAddress, - "registryAddress": config.registryAddress, - }, - }, - }) -} - -// https://github.com/GoogleContainerTools/kaniko/issues/1592 -// https://github.com/kyma-project/kyma/issues/13051 -func (b *builder) addDefaultServerlessKanikoForce() *builder { - return b.addDefaultValues(map[string]interface{}{ - "serverless": map[string]interface{}{ - "containers": map[string]interface{}{ - "manager": map[string]interface{}{ - "envs": map[string]interface{}{ - "functionBuildExecutorArgs": map[string]interface{}{ - "value": "--insecure,--skip-tls-verify,--skip-unused-stages,--log-format=text,--cache=true,--force", - }, - }, - }, - }, - }, - }) -} - func (b *builder) addDefaultk3dValuesForIstio() *builder { return b.addDefaultValues(map[string]interface{}{ "istio": map[string]interface{}{ diff --git a/internal/deploy/values/values.go b/internal/deploy/values/values.go index f7e68ac7f..8365cc8ce 100644 --- a/internal/deploy/values/values.go +++ b/internal/deploy/values/values.go @@ -2,7 +2,6 @@ package values import ( "encoding/base64" - "fmt" "os" "path/filepath" @@ -46,20 +45,10 @@ func Merge(sources Sources, workspaceDir string, clusterInfo clusterinfo.Info) ( } func addClusterSpecificDefaults(builder *builder, clusterInfo clusterinfo.Info) { - if k3d, isK3d := clusterInfo.(clusterinfo.K3d); isK3d { - - k3dRegistry := fmt.Sprintf("k3d-%s-registry:5000", k3d.ClusterName) - defaultRegistryConfig := serverlessRegistryConfig{ - enable: false, - registryAddress: k3dRegistry, - serverAddress: k3dRegistry, - internalServerAddress: k3dRegistry, - } + if _, isK3d := clusterInfo.(clusterinfo.K3d); isK3d { builder. - addDefaultServerlessRegistryConfig(defaultRegistryConfig). addDefaultGlobalDomainName(defaultLocalKymaDomain). addDefaultGlobalTLSCrtAndKey(defaultLocalTLSCrtEnc, defaultLocalTLSKeyEnc). - addDefaultServerlessKanikoForce(). addDefaultk3dValuesForIstio() } else if gardener, isGardener := clusterInfo.(clusterinfo.Gardener); isGardener { builder.addDefaultGlobalDomainName(gardener.Domain) diff --git a/internal/deploy/values/values_test.go b/internal/deploy/values/values_test.go index fc2d092ee..4ad04d0fb 100644 --- a/internal/deploy/values/values_test.go +++ b/internal/deploy/values/values_test.go @@ -192,65 +192,6 @@ func TestMerge(t *testing.T) { "tlsCrt": defaultLocalTLSCrtEnc, "tlsKey": defaultLocalTLSKeyEnc, }, - "serverless": map[string]interface{}{ - "dockerRegistry": map[string]interface{}{ - "enableInternal": false, - "internalServerAddress": "k3d-foo-registry:5000", - "serverAddress": "k3d-foo-registry:5000", - "registryAddress": "k3d-foo-registry:5000", - }, - "containers": map[string]interface{}{ - "manager": map[string]interface{}{ - "envs": map[string]interface{}{ - "functionBuildExecutorArgs": map[string]interface{}{ - "value": "--insecure,--skip-tls-verify,--skip-unused-stages,--log-format=text,--cache=true,--force", - }, - }, - }, - }, - }, - "istio": map[string]interface{}{ - "helmValues": map[string]interface{}{ - "cni": map[string]string{ - "cniConfDir": "/var/lib/rancher/k3s/agent/etc/cni/net.d", - "cniBinDir": "/bin", - }, - }, - }, - } - - require.NoError(t, err) - require.Truef(t, reflect.DeepEqual(expected, actual), "want: %#v\n got: %#v\n", expected, actual) - }) - - t.Run("Serverless registry overrides", func(t *testing.T) { - src := Sources{ValueFiles: []string{"./testdata/registry-overrides.yaml"}} - actual, err := Merge(src, "testdata", clusterinfo.K3d{ClusterName: "foo"}) - - expected := Values{ - "global": map[string]interface{}{ - "domainName": "local.kyma.dev", - "tlsCrt": defaultLocalTLSCrtEnc, - "tlsKey": defaultLocalTLSKeyEnc, - }, - "serverless": map[string]interface{}{ - "dockerRegistry": map[string]interface{}{ - "enableInternal": true, - "password": "secret password", - "internalServerAddress": "internal-address", - "serverAddress": "external-address", - "registryAddress": "external-push-address", - }, - "containers": map[string]interface{}{ - "manager": map[string]interface{}{ - "envs": map[string]interface{}{ - "functionBuildExecutorArgs": map[string]interface{}{ - "value": "--insecure,--skip-tls-verify,--skip-unused-stages,--log-format=text,--cache=true,--force", - }, - }, - }, - }, - }, "istio": map[string]interface{}{ "helmValues": map[string]interface{}{ "cni": map[string]string{ @@ -271,7 +212,6 @@ func TestMerge(t *testing.T) { "global.domainName=github.com", "global.tlsCrt=github_tls_crt", "global.tlsKey=github_tls_key", - "serverless.dockerRegistry.enableInternal=true", }, }, "testdata", clusterinfo.K3d{ClusterName: "foo"}) @@ -281,23 +221,6 @@ func TestMerge(t *testing.T) { "tlsCrt": "github_tls_crt", "tlsKey": "github_tls_key", }, - "serverless": map[string]interface{}{ - "dockerRegistry": map[string]interface{}{ - "enableInternal": true, - "internalServerAddress": "k3d-foo-registry:5000", - "serverAddress": "k3d-foo-registry:5000", - "registryAddress": "k3d-foo-registry:5000", - }, - "containers": map[string]interface{}{ - "manager": map[string]interface{}{ - "envs": map[string]interface{}{ - "functionBuildExecutorArgs": map[string]interface{}{ - "value": "--insecure,--skip-tls-verify,--skip-unused-stages,--log-format=text,--cache=true,--force", - }, - }, - }, - }, - }, "istio": map[string]interface{}{ "helmValues": map[string]interface{}{ "cni": map[string]string{ @@ -323,23 +246,6 @@ func TestMerge(t *testing.T) { "tlsCrt": defaultLocalTLSCrtEnc, "tlsKey": defaultLocalTLSKeyEnc, }, - "serverless": map[string]interface{}{ - "dockerRegistry": map[string]interface{}{ - "enableInternal": false, - "internalServerAddress": "k3d-foo-registry:5000", - "serverAddress": "k3d-foo-registry:5000", - "registryAddress": "k3d-foo-registry:5000", - }, - "containers": map[string]interface{}{ - "manager": map[string]interface{}{ - "envs": map[string]interface{}{ - "functionBuildExecutorArgs": map[string]interface{}{ - "value": "--insecure,--skip-tls-verify,--skip-unused-stages,--log-format=text,--cache=true,--force", - }, - }, - }, - }, - }, "istio": map[string]interface{}{ "helmValues": map[string]interface{}{ "cni": map[string]string{ From bfde5367f36097541c34e20588b41229d3cf27d9 Mon Sep 17 00:00:00 2001 From: Nesma Badr Date: Fri, 6 Oct 2023 16:22:34 +0200 Subject: [PATCH 02/10] test: CLI E2E tests with template operator (#1792) * Setup e2e tests action * Forcing an empty commit. * Add go file + make target * add Run E2E tests step * add e2e test * refactor existing E2E tests * remove redundant step in e2e yaml * trigger the pipeline * editing go file to trigger pipeline * fix yaml file * remove unneeded expect statement * some fixes * some fixes * add suite_test.go * ginkgo bootstrap * add e2e_suite_test * remove unnecessary log * fixes * fixes * start test implementation * disable running e2e from * create module test changes * exclude e2e from test target * kyma alpha deploy * fix * Forcing an empty commit. * fix * fix * fix * fix * fix * fix * fix * Increase timeout * fix * fix * fix * fixes * fixes * fix * Reduce timeout * fixes * fixes * fixes * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * enable module * enable module * stop running create module command for the rest of the e2e * stop running create module command for the rest of the e2e * debug * validate resources after enablement * fix linting * debugging * debugging * debugging * debugging * fixes * fixes * uncomment and add module name * print kyma.status.modules * add v1extensions scheme * increase timeout * debugging * debugging * revert module creation test * fix linting * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * disable module * add new template-operator * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix linting * remove unneeded env variables * remove unneeded env variables * debug error * debug error * debug error * fixes * Oleksandr's comments * fix test * remove * fix test * fix test * comment 1 * Oleksandr's PR comments * fix * fix * fix * fix * Rephrase the Describe * Oleksandr's comments * Xin's comments * Oleksandr's comments * flatten * fix linting * fixes * fixes * fixes * fix create module * remove duplicate targets * Forcing an empty commit. * Xin's comment * Xin's comment * fix status * fix status * fix status * fix status * comment * remove unneeded consts --- .github/workflows/test-e2e-create-module.yml | 10 +- .../{test-smoke.yml => test-e2e.yml} | 16 +- Makefile | 2 +- go.mod | 5 +- go.sum | 4 +- tests/e2e/Makefile | 12 +- .../kyma_create_module_test.go | 30 +-- tests/e2e/deploy_enable_disable_test.go | 138 +++++++++++++ tests/e2e/e2e_suite_test.go | 58 ++++++ ...uletemplate_template_operator_regular.yaml | 73 +++++++ ...ate_template_operator_regular_warning.yaml | 73 +++++++ tests/e2e/util.go | 191 ++++++++++++++++++ 12 files changed, 569 insertions(+), 43 deletions(-) rename .github/workflows/{test-smoke.yml => test-e2e.yml} (81%) rename tests/e2e/{ => create_module}/kyma_create_module_test.go (84%) create mode 100644 tests/e2e/deploy_enable_disable_test.go create mode 100644 tests/e2e/e2e_suite_test.go create mode 100644 tests/e2e/module_templates/moduletemplate_template_operator_regular.yaml create mode 100644 tests/e2e/module_templates/moduletemplate_template_operator_regular_warning.yaml diff --git a/.github/workflows/test-e2e-create-module.yml b/.github/workflows/test-e2e-create-module.yml index 60623b2d3..1f754fb91 100644 --- a/.github/workflows/test-e2e-create-module.yml +++ b/.github/workflows/test-e2e-create-module.yml @@ -17,7 +17,7 @@ jobs: e2e: strategy: matrix: - e2e-test: [ "create_module_kubebuilder_project", "create_module_module_config"] + e2e-test: [ "test-kubebuilder-module-creation", "test-moduleconfig-module-creation"] name: "Run E2E tests" runs-on: ubuntu-latest env: @@ -33,7 +33,7 @@ jobs: go-version-file: 'go.mod' cache-dependency-path: 'go.sum' - name: Build Kyma CLI - run: | + run: | make resolve validate build-linux chmod +x ./bin/kyma-linux ls -la ./bin @@ -54,7 +54,7 @@ jobs: run: | k3d registry create oci.localhost --port 5001 - name: Run create module with kubebuilder-project - if: ${{ matrix.e2e-test == 'create_module_kubebuilder_project' }} + if: ${{ matrix.e2e-test == 'test-kubebuilder-module-creation' }} run: | kyma alpha create module \ --name kyma-project.io/module/template-operator \ @@ -67,7 +67,7 @@ jobs: --sec-scanners-config ./template-operator/sec-scanners-config.yaml echo "MODULE_TEMPLATE_PATH=/tmp/kubebuilder-template.yaml" >> "$GITHUB_ENV" - name: Run create module with module-config - if: ${{ matrix.e2e-test == 'create_module_module_config' }} + if: ${{ matrix.e2e-test == 'test-moduleconfig-module-creation' }} run: | cd ./template-operator make build-manifests @@ -83,4 +83,4 @@ jobs: - name: Verify module template run: | echo $MODULE_TEMPLATE_PATH - make -C tests/e2e ${{ matrix.e2e-test }} \ No newline at end of file + make -C tests/e2e test-module-creation \ No newline at end of file diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-e2e.yml similarity index 81% rename from .github/workflows/test-smoke.yml rename to .github/workflows/test-e2e.yml index 7e3d6dd9e..7f56eabeb 100644 --- a/.github/workflows/test-smoke.yml +++ b/.github/workflows/test-e2e.yml @@ -1,4 +1,4 @@ -name: TestSuite Smoke +name: TestSuite E2E on: push: @@ -14,20 +14,22 @@ on: - 'go.sum' - '**.go' jobs: - cli-deploy: - name: "kyma deploy" + e2e-tests: + name: "Run E2E tests" runs-on: ubuntu-latest env: - LIFECYCLE_MANAGER: ${{ github.repository }} K3D_VERSION: v5.4.7 steps: - - name: Checkout + - name: Checkout Kyma CLI uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v4 with: go-version-file: 'go.mod' cache-dependency-path: 'go.sum' + - name: Set up kubectl + uses: azure/setup-kubectl@v3 + id: install - name: Build Kyma CLI run: | make resolve validate build-linux @@ -48,5 +50,5 @@ jobs: --name kyma - name: Update Kubeconfigs run: k3d kubeconfig merge -a -d - - name: Run kyma deploy - run: kyma --ci alpha deploy + - name: Run E2E tests + run: make -C tests/e2e test-module-enabling-disabling \ No newline at end of file diff --git a/Makefile b/Makefile index 399a00d1b..8a46769a6 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ docs: .PHONY: test test: - go test -race -coverprofile=cover.out ./... + go test `go list ./... | grep -v /tests/e2e` -race -coverprofile=cover.out @echo "Total test coverage: $$(go tool cover -func=cover.out | grep total | awk '{print $$3}')" @rm cover.out diff --git a/go.mod b/go.mod index 6dd9d96c9..447e48d60 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,8 @@ require ( github.com/kyma-project/hydroform/provision v0.0.0-20230831071441-f3501c89bace github.com/kyma-project/lifecycle-manager v0.0.0-20230911065458-6926c58bcd43 github.com/mandelsoft/vfs v0.0.0-20230714093241-d557f163aecd + github.com/onsi/ginkgo/v2 v2.12.1 + github.com/onsi/gomega v1.27.10 github.com/open-component-model/ocm v0.3.0-rc.1 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc4 @@ -130,6 +132,7 @@ require ( github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-migrate/migrate/v4 v4.15.1 // indirect @@ -142,6 +145,7 @@ require ( github.com/google/go-github/v45 v45.2.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.1 // indirect github.com/gorilla/mux v1.8.0 // indirect @@ -198,7 +202,6 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/onsi/gomega v1.27.10 // indirect github.com/opencontainers/runc v1.1.5 // indirect github.com/otiai10/copy v1.9.0 // indirect github.com/panjf2000/ants/v2 v2.7.1 // indirect diff --git a/go.sum b/go.sum index 9565e8e2a..64cb4a4e5 100644 --- a/go.sum +++ b/go.sum @@ -1344,8 +1344,8 @@ github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= diff --git a/tests/e2e/Makefile b/tests/e2e/Makefile index f5cb00c9a..c30ce8d41 100644 --- a/tests/e2e/Makefile +++ b/tests/e2e/Makefile @@ -31,10 +31,10 @@ help: ## Display this help. ##@ E2E Tests -.PHONY: create_module_kubebuilder_project -create_module_kubebuilder_project: - go test --tags=create_module_kubebuilder_project +.PHONY: test-module-creation +test-module-creation: + go test ./create_module -run "Test_ModuleTemplate" -.PHONY: create_module_module_config -create_module_module_config: - go test --tags=create_module_module_config +.PHONY: test-module-enabling-disabling +test-module-enabling-disabling: + go test -ginkgo.v -ginkgo.focus "Kyma CLI deploy, enable and disable commands usage" \ No newline at end of file diff --git a/tests/e2e/kyma_create_module_test.go b/tests/e2e/create_module/kyma_create_module_test.go similarity index 84% rename from tests/e2e/kyma_create_module_test.go rename to tests/e2e/create_module/kyma_create_module_test.go index 4f651e361..3afd58025 100644 --- a/tests/e2e/kyma_create_module_test.go +++ b/tests/e2e/create_module/kyma_create_module_test.go @@ -1,6 +1,4 @@ -//go:build create_module_kubebuilder_project || create_module_module_config - -package e2e_test +package create_module_test import ( "os" @@ -17,8 +15,6 @@ import ( "github.com/open-component-model/ocm/pkg/contexts/ocm/cpi" "github.com/open-component-model/ocm/pkg/contexts/ocm/repositories/genericocireg" ocmOCIReg "github.com/open-component-model/ocm/pkg/contexts/ocm/repositories/ocireg" - "gopkg.in/yaml.v3" - "github.com/stretchr/testify/assert" ) @@ -66,25 +62,17 @@ func Test_ModuleTemplate(t *testing.T) { sourceAccessSpec, err := ocm.DefaultContext().AccessSpecForSpec(source.Access) assert.Nil(t, err) githubAccessSpec, ok := sourceAccessSpec.(*github.AccessSpec) + assert.Equal(t, ok, true) assert.Equal(t, githubAccessSpec.Type, github.Type) assert.Contains(t, testRepoURL, githubAccessSpec.RepoURL) // test security scan labels secScanLabels := descriptor.Sources[0].Labels - - var devBranch string - yaml.Unmarshal(secScanLabels[1].Value, &devBranch) - assert.Equal(t, "main", devBranch) - - var rcTag string - yaml.Unmarshal(secScanLabels[2].Value, &rcTag) - assert.Equal(t, "0.5.0", rcTag) - - var language string - yaml.Unmarshal(secScanLabels[3].Value, &language) - assert.Equal(t, "golang-mod", language) - - var exclude string - yaml.Unmarshal(secScanLabels[4].Value, &exclude) - assert.Equal(t, "**/test/**,**/*_test.go", exclude) + assert.Equal(t, map[string]string{ + "git.kyma-project.io/ref": "refs/heads/main", + "scan.security.kyma-project.io/dev-branch": "main", + "scan.security.kyma-project.io/rc-tag": "0.5.0", + "scan.security.kyma-project.io/language": "golang-mod", + "scan.security.kyma-project.io/exclude": "**/test/**,**/*_test.go", + }, e2e.Flatten(secScanLabels)) } diff --git a/tests/e2e/deploy_enable_disable_test.go b/tests/e2e/deploy_enable_disable_test.go new file mode 100644 index 000000000..8fcb7db8b --- /dev/null +++ b/tests/e2e/deploy_enable_disable_test.go @@ -0,0 +1,138 @@ +package e2e_test + +import ( + "github.com/kyma-project/cli/internal/cli" + . "github.com/kyma-project/cli/tests/e2e" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Kyma CLI deploy, enable and disable commands usage", Ordered, func() { + kcpSystemNamespace := "kcp-system" + deployments := map[string]string{ + "template-operator-controller-manager": "template-operator-system", + "sample-redis-deployment": "manifest-redis", + } + + Context("Given a Kyma Cluster", func() { + It("When `kyma alpha deploy` command is executed", func() { + Expect(ExecuteKymaDeployCommand()).To(Succeed()) + + By("Then the Kyma CR is in a ready state") + Eventually(KymaCRIsInReadyState). + WithContext(ctx). + WithArguments(k8sClient, cli.KymaNameDefault, cli.KymaNamespaceDefault). + Should(BeTrue()) + + By("And the Lifecycle Manager is in a ready state") + Eventually(DeploymentIsReady). + WithContext(ctx). + WithArguments(k8sClient, "lifecycle-manager-controller-manager", kcpSystemNamespace). + Should(BeTrue()) + }) + }) + + Context("Given a valid Template Operator module template", func() { + It("When a Template Operator module is applied", func() { + Expect(ApplyModuleTemplate("module_templates/moduletemplate_template_operator_regular.yaml")). + To(Succeed()) + + By("And the Template Operator gets enabled") + Expect(EnableKymaModuleWithReadyState("template-operator")).To(Succeed()) + Eventually(KymaContainsModuleInExpectedState). + WithContext(ctx). + WithArguments(k8sClient, + cli.KymaNameDefault, + cli.KymaNamespaceDefault, + "template-operator", + v1beta2.StateReady). + Should(BeTrue()) + }) + + It("Then Template Operator resources are deployed in the cluster", func() { + Eventually(ModuleResourcesAreReady). + WithContext(ctx). + WithArguments(k8sClient, "samples.operator.kyma-project.io", deployments). + Should(BeTrue()) + }) + + It("And the Template Operator's CR state is ready", func() { + Eventually(CrIsInExpectedState). + WithContext(ctx). + WithArguments("sample", "sample-yaml", "kyma-system", v1beta2.StateReady). + Should(BeTrue()) + }) + }) + + Context("Given a Template Operator module in a ready state", func() { + It("When `kyma disable module` command is execute", func() { + Expect(DisableModuleOnKyma("template-operator")).To(Succeed()) + + Eventually(KymaCRIsInReadyState). + WithContext(ctx). + WithArguments(k8sClient, cli.KymaNameDefault, cli.KymaNamespaceDefault). + Should(BeTrue()) + }) + + It("Then the Template Operator's resources are removed from the cluster", func() { + Eventually(ModuleResourcesAreReady). + WithContext(ctx). + WithArguments(k8sClient, "samples.operator.kyma-project.io", deployments). + Should(BeFalse()) + }) + }) + + Context("Given a warning state Template Operator module template", func() { + It("When a Template Operator module is applied", func() { + Expect(ApplyModuleTemplate( + "module_templates/moduletemplate_template_operator_regular_warning.yaml")). + To(Succeed()) + }) + + It("And the Template Operator enable command invoked", func() { + Expect(EnableKymaModuleWithWarningState("template-operator")).To(Succeed()) + + Eventually(KymaContainsModuleInExpectedState). + WithContext(ctx). + WithArguments(k8sClient, + cli.KymaNameDefault, + cli.KymaNamespaceDefault, + "template-operator", + v1beta2.StateWarning). + Should(BeTrue()) + }) + + It("Then the Template Operator's resources are deployed in the cluster", func() { + Eventually(ModuleResourcesAreReady). + WithContext(ctx). + WithArguments(k8sClient, "samples.operator.kyma-project.io", deployments). + Should(BeTrue()) + }) + + It("And the Template Operator's CR state is in a warning state", func() { + Eventually(CrIsInExpectedState). + WithContext(ctx). + WithArguments("sample", "sample-yaml", "kyma-system", v1beta2.StateWarning). + Should(BeTrue()) + }) + }) + + Context("Given a Template Operator module in a warning state", func() { + It("When `kyma disable module` command is executed", func() { + Expect(DisableModuleOnKyma("template-operator")).To(Succeed()) + + Eventually(KymaCRIsInReadyState). + WithContext(ctx). + WithArguments(k8sClient, cli.KymaNameDefault, cli.KymaNamespaceDefault). + Should(BeTrue()) + }) + + It("Then Template Operator's resources are removed from the cluster", func() { + Eventually(ModuleResourcesAreReady). + WithContext(ctx). + WithArguments(k8sClient, "samples.operator.kyma-project.io", deployments). + Should(BeFalse()) + }) + }) +}) diff --git a/tests/e2e/e2e_suite_test.go b/tests/e2e/e2e_suite_test.go new file mode 100644 index 000000000..9e27114b5 --- /dev/null +++ b/tests/e2e/e2e_suite_test.go @@ -0,0 +1,58 @@ +package e2e_test + +import ( + "context" + "testing" + "time" + + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/pkg/log" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "go.uber.org/zap/zapcore" + v1extensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +const ( + timeout = 60 * time.Second + interval = 1 * time.Second +) + +var ( + ctx context.Context + cancel context.CancelFunc + k8sClient client.Client +) + +func TestE2e(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "E2e Suite") +} + +var _ = BeforeSuite(func() { + ctx, cancel = context.WithCancel(context.TODO()) + logf.SetLogger(log.ConfigLogger(9, zapcore.AddSync(GinkgoWriter))) + + SetDefaultEventuallyPollingInterval(interval) + SetDefaultEventuallyTimeout(timeout) + + kubeConfig := ctrl.GetConfigOrDie() + Expect(kubeConfig).NotTo(BeNil()) + var err error + Expect(v1beta2.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) + Expect(v1extensions.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) + + k8sClient, err = client.New(kubeConfig, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + go func() { + defer GinkgoRecover() + }() +}) + +var _ = AfterSuite(func() { + cancel() +}) diff --git a/tests/e2e/module_templates/moduletemplate_template_operator_regular.yaml b/tests/e2e/module_templates/moduletemplate_template_operator_regular.yaml new file mode 100644 index 000000000..c7e6d9707 --- /dev/null +++ b/tests/e2e/module_templates/moduletemplate_template_operator_regular.yaml @@ -0,0 +1,73 @@ +apiVersion: operator.kyma-project.io/v1beta2 +kind: ModuleTemplate +metadata: + name: template-operator-regular + namespace: kcp-system + labels: + "operator.kyma-project.io/module-name": "template-operator" + annotations: + "operator.kyma-project.io/is-cluster-scoped": "false" +spec: + channel: regular + data: + apiVersion: operator.kyma-project.io/v1alpha1 + kind: Sample + metadata: + name: sample-yaml + spec: + resourceFilePath: "./module-data/yaml" + descriptor: + component: + componentReferences: [] + labels: + - name: security.kyma-project.io/scan + value: enabled + version: v1 + name: kyma-project.io/template-operator + provider: '{"name":"kyma-project.io","labels":[{"name":"kyma-project.io/built-by","value":"cli","version":"v1"}]}' + repositoryContexts: + - baseUrl: europe-west3-docker.pkg.dev/sap-kyma-jellyfish-dev/template-operator + componentNameMapping: urlPath + type: OCIRegistry + resources: + - access: + globalAccess: + digest: sha256:8afd57bdf0b69b4eaa25e6baee8782e106994070b9d0ef645dfc42d1f9345966 + mediaType: application/octet-stream + ref: europe-west3-docker.pkg.dev/sap-kyma-jellyfish-dev/template-operator/component-descriptors/kyma-project.io/template-operator + size: 12810 + type: ociBlob + localReference: sha256:8afd57bdf0b69b4eaa25e6baee8782e106994070b9d0ef645dfc42d1f9345966 + mediaType: application/octet-stream + type: localBlob + name: raw-manifest + relation: local + type: yaml + version: v1.0.0-e2e + sources: + - access: + commit: df40b4455b437a412fe5656143bacd6b542b3a7c + repoUrl: github.com/kyma-project/template-operator + type: gitHub + labels: + - name: git.kyma-project.io/ref + value: refs/heads/sec_scanners_change + version: v1 + - name: scan.security.kyma-project.io/dev-branch + value: main + version: v1 + - name: scan.security.kyma-project.io/rc-tag + value: 0.5.0 + version: v1 + - name: scan.security.kyma-project.io/language + value: golang-mod + version: v1 + - name: scan.security.kyma-project.io/exclude + value: '**/test/**,**/*_test.go' + version: v1 + name: module-sources + type: Github + version: v1.0.0-e2e + version: v1.0.0-e2e + meta: + schemaVersion: v2 diff --git a/tests/e2e/module_templates/moduletemplate_template_operator_regular_warning.yaml b/tests/e2e/module_templates/moduletemplate_template_operator_regular_warning.yaml new file mode 100644 index 000000000..8ca5226a7 --- /dev/null +++ b/tests/e2e/module_templates/moduletemplate_template_operator_regular_warning.yaml @@ -0,0 +1,73 @@ +apiVersion: operator.kyma-project.io/v1beta2 +kind: ModuleTemplate +metadata: + name: template-operator-regular + namespace: kcp-system + labels: + "operator.kyma-project.io/module-name": "template-operator" + annotations: + "operator.kyma-project.io/is-cluster-scoped": "false" +spec: + channel: regular + data: + apiVersion: operator.kyma-project.io/v1alpha1 + kind: Sample + metadata: + name: sample-yaml + spec: + resourceFilePath: "./module-data/yaml" + descriptor: + component: + componentReferences: [] + labels: + - name: security.kyma-project.io/scan + value: enabled + version: v1 + name: kyma-project.io/template-operator + provider: '{"name":"kyma-project.io","labels":[{"name":"kyma-project.io/built-by","value":"cli","version":"v1"}]}' + repositoryContexts: + - baseUrl: europe-west3-docker.pkg.dev/sap-kyma-jellyfish-dev/template-operator + componentNameMapping: urlPath + type: OCIRegistry + resources: + - access: + globalAccess: + digest: sha256:e88f3d1a80dbce2084f4991905a3e9847a58bd0e5b666754aa9105b9d49e82ba + mediaType: application/octet-stream + ref: europe-west3-docker.pkg.dev/sap-kyma-jellyfish-dev/template-operator/component-descriptors/kyma-project.io/template-operator + size: 12812 + type: ociBlob + localReference: sha256:e88f3d1a80dbce2084f4991905a3e9847a58bd0e5b666754aa9105b9d49e82ba + mediaType: application/octet-stream + type: localBlob + name: raw-manifest + relation: local + type: yaml + version: v1.0.0-e2e-warning + sources: + - access: + commit: df40b4455b437a412fe5656143bacd6b542b3a7c + repoUrl: github.com/kyma-project/template-operator + type: gitHub + labels: + - name: git.kyma-project.io/ref + value: refs/heads/sec_scanners_change + version: v1 + - name: scan.security.kyma-project.io/dev-branch + value: main + version: v1 + - name: scan.security.kyma-project.io/rc-tag + value: 0.5.0 + version: v1 + - name: scan.security.kyma-project.io/language + value: golang-mod + version: v1 + - name: scan.security.kyma-project.io/exclude + value: '**/test/**,**/*_test.go' + version: v1 + name: module-sources + type: Github + version: v1.0.0-e2e-warning + version: v1.0.0-e2e-warning + meta: + schemaVersion: v2 diff --git a/tests/e2e/util.go b/tests/e2e/util.go index 36d094a24..d6525143b 100644 --- a/tests/e2e/util.go +++ b/tests/e2e/util.go @@ -1,10 +1,32 @@ package e2e import ( + "context" + "fmt" "os" + "os/exec" + "strings" "github.com/kyma-project/lifecycle-manager/api/v1beta2" + . "github.com/onsi/ginkgo/v2" //nolint:stylecheck,revive + v1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1" + "github.com/pkg/errors" + appsv1 "k8s.io/api/apps/v1" + v1extensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/util/yaml" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var ( + errKymaDeployCommandFailed = errors.New("failed to run kyma alpha deploy") + errModuleTemplateNotApplied = errors.New("failed to apply ModuleTemplate") + errModuleEnablingFailed = errors.New("failed to enable module") + errModuleDisablingFailed = errors.New("failed to disable module") +) + +const ( + exitCodeNoError = 0 + exitCodeWarning = 2 ) func ReadModuleTemplate(filepath string) (*v1beta2.ModuleTemplate, error) { @@ -16,3 +38,172 @@ func ReadModuleTemplate(filepath string) (*v1beta2.ModuleTemplate, error) { err = yaml.Unmarshal(moduleFile, &moduleTemplate) return moduleTemplate, err } + +func ExecuteKymaDeployCommand() error { + deployCmd := exec.Command("kyma", "alpha", "deploy") + deployOut, err := deployCmd.CombinedOutput() + if err != nil { + return fmt.Errorf("%w: %v", errKymaDeployCommandFailed, err) + } + + if !strings.Contains(string(deployOut), "Kyma CR deployed and Ready") { + return errKymaDeployCommandFailed + } + + return nil +} + +func DeploymentIsReady(ctx context.Context, + k8sClient client.Client, + deploymentName string, + namespace string) bool { + var deployment appsv1.Deployment + err := k8sClient.Get(ctx, client.ObjectKey{ + Namespace: namespace, + Name: deploymentName, + }, &deployment) + + GinkgoWriter.Println("Available replicas:", deployment.Status.AvailableReplicas) + return err == nil && deployment.Status.AvailableReplicas != 0 +} + +func KymaCRIsInReadyState(ctx context.Context, + k8sClient client.Client, + kymaName string, + namespace string) bool { + var kyma v1beta2.Kyma + err := k8sClient.Get(ctx, client.ObjectKey{ + Namespace: namespace, + Name: kymaName, + }, &kyma) + + return err == nil && kyma.Status.State == v1beta2.StateReady +} + +func ApplyModuleTemplate( + moduleTemplatePath string) error { + cmd := exec.Command("kubectl", "apply", "-f", moduleTemplatePath) + + _, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("%w: %v", errModuleTemplateNotApplied, err) + } + + return nil +} + +func enableKymaModuleWithExpectedExitCode(moduleName string, expectedExitCode int) error { + cmd := exec.Command("kyma", "alpha", "enable", "module", moduleName, "-w") + err := cmd.Run() + var exitCode int + if exitErr, ok := err.(*exec.ExitError); ok { + exitCode = exitErr.ExitCode() + } else { + exitCode = cmd.ProcessState.ExitCode() + } + + GinkgoWriter.Println("Exit code", exitCode) + if exitCode != expectedExitCode { + return fmt.Errorf("%w: %v", errModuleEnablingFailed, err) + } + return nil +} + +func EnableKymaModuleWithReadyState(moduleName string) error { + return enableKymaModuleWithExpectedExitCode(moduleName, exitCodeNoError) +} + +func EnableKymaModuleWithWarningState(moduleName string) error { + return enableKymaModuleWithExpectedExitCode(moduleName, exitCodeWarning) + +} + +func DisableModuleOnKyma(moduleName string) error { + cmd := exec.Command("kyma", "alpha", "disable", "module", moduleName, "-w") + err := cmd.Run() + var exitCode int + if exitErr, ok := err.(*exec.ExitError); ok { + exitCode = exitErr.ExitCode() + } else { + exitCode = cmd.ProcessState.ExitCode() + } + + GinkgoWriter.Println("Exit code", exitCode) + if exitCode != 0 { + return fmt.Errorf("%w: %v", errModuleDisablingFailed, err) + } + return nil +} + +func CRDIsAvailable(ctx context.Context, + k8sClient client.Client, + name string) bool { + var crd v1extensions.CustomResourceDefinition + err := k8sClient.Get(ctx, client.ObjectKey{ + Name: name, + }, &crd) + + return err == nil +} + +func CrIsInExpectedState(resourceType string, + resourceName string, + namespace string, + expectedState v1beta2.State) bool { + cmd := exec.Command("kubectl", "get", resourceType, resourceName, "-n", + namespace, "-o", "jsonpath='{.status.state}'") + + statusOutput, err := cmd.CombinedOutput() + if err != nil { + return false + } + + GinkgoWriter.Println(string(statusOutput)) + + return err == nil && strings.Contains(string(statusOutput), string(expectedState)) +} + +func KymaContainsModuleInExpectedState(ctx context.Context, + k8sClient client.Client, + kymaName string, + namespace string, + moduleName string, + expectedState v1beta2.State) bool { + var kyma v1beta2.Kyma + err := k8sClient.Get(ctx, client.ObjectKey{ + Namespace: namespace, + Name: kymaName, + }, &kyma) + + GinkgoWriter.Println(kyma.Status.Modules) + + return err == nil && kyma.Status.Modules != nil && kyma.Status.Modules[0].Name == moduleName && + kyma.Status.Modules[0].State == expectedState +} + +func ModuleResourcesAreReady(ctx context.Context, + k8sClient client.Client, + crdName string, + deploymentNamesAndNamespaces map[string]string) bool { + if !CRDIsAvailable(ctx, k8sClient, crdName) { + return false + } + for k, v := range deploymentNamesAndNamespaces { + if !DeploymentIsReady(ctx, k8sClient, k, v) { + return false + } + } + + return true +} + +func Flatten(labels v1.Labels) map[string]string { + labelsMap := make(map[string]string) + for _, l := range labels { + var value string + _ = yaml.Unmarshal(l.Value, &value) + labelsMap[l.Name] = value + } + + return labelsMap +} From 5145bb19b3d879c92a308c10a277f102d2b55885 Mon Sep 17 00:00:00 2001 From: Nesma Badr Date: Mon, 9 Oct 2023 16:28:31 +0200 Subject: [PATCH 03/10] fix: Error out if create module is executed with an existing version without the overwrite flag (#1797) * Setup e2e tests action * Forcing an empty commit. * Add go file + make target * add Run E2E tests step * add e2e test * refactor existing E2E tests * remove redundant step in e2e yaml * trigger the pipeline * editing go file to trigger pipeline * fix yaml file * remove unneeded expect statement * some fixes * some fixes * add suite_test.go * ginkgo bootstrap * add e2e_suite_test * remove unnecessary log * fixes * fixes * start test implementation * disable running e2e from * create module test changes * exclude e2e from test target * kyma alpha deploy * fix * Forcing an empty commit. * fix * fix * fix * fix * fix * fix * fix * Increase timeout * fix * fix * fix * fixes * fixes * fix * Reduce timeout * fixes * fixes * fixes * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * debug error * enable module * enable module * stop running create module command for the rest of the e2e * stop running create module command for the rest of the e2e * debug * validate resources after enablement * fix linting * debugging * debugging * debugging * debugging * fixes * fixes * uncomment and add module name * print kyma.status.modules * add v1extensions scheme * increase timeout * debugging * debugging * revert module creation test * fix linting * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * disable module * add new template-operator * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix linting * remove unneeded env variables * remove unneeded env variables * debug error * debug error * debug error * fixes * Oleksandr's comments * fix test * remove * fix test * fix test * comment 1 * Oleksandr's PR comments * fix * fix * fix * fix * fix implementation * Add e2e test * fix test * fix * fix * debug test * fix linting * debuggging * Rephrase the Describe * Oleksandr's comments * debug test * debug test * debug test * fix target * fix error message --- .github/workflows/test-e2e-create-module.yml | 13 ++++++-- pkg/module/remote.go | 10 ++++++ tests/e2e/Makefile | 4 +++ .../kyma_create_module_same_version_test.go | 25 +++++++++++++++ tests/e2e/util.go | 32 ++++++++++++++++--- 5 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 tests/e2e/create_module/kyma_create_module_same_version_test.go diff --git a/.github/workflows/test-e2e-create-module.yml b/.github/workflows/test-e2e-create-module.yml index 1f754fb91..0aa381028 100644 --- a/.github/workflows/test-e2e-create-module.yml +++ b/.github/workflows/test-e2e-create-module.yml @@ -17,7 +17,8 @@ jobs: e2e: strategy: matrix: - e2e-test: [ "test-kubebuilder-module-creation", "test-moduleconfig-module-creation"] + e2e-test: [ "test-kubebuilder-module-creation", "test-moduleconfig-module-creation", + "test-same-version-module-creation"] name: "Run E2E tests" runs-on: ubuntu-latest env: @@ -67,7 +68,7 @@ jobs: --sec-scanners-config ./template-operator/sec-scanners-config.yaml echo "MODULE_TEMPLATE_PATH=/tmp/kubebuilder-template.yaml" >> "$GITHUB_ENV" - name: Run create module with module-config - if: ${{ matrix.e2e-test == 'test-moduleconfig-module-creation' }} + if: ${{ matrix.e2e-test == 'test-moduleconfig-module-creation' || matrix.e2e-test == 'test-same-version-module-creation'}} run: | cd ./template-operator make build-manifests @@ -81,6 +82,12 @@ jobs: --output /tmp/module-config-template.yaml echo "MODULE_TEMPLATE_PATH=/tmp/module-config-template.yaml" >> "$GITHUB_ENV" - name: Verify module template + if: ${{ matrix.e2e-test == 'test-moduleconfig-module-creation' || matrix.e2e-test == 'test-kubebuilder-module-creation'}} run: | echo $MODULE_TEMPLATE_PATH - make -C tests/e2e test-module-creation \ No newline at end of file + make -C tests/e2e test-module-creation + - name: Run E2E tests + if: ${{ matrix.e2e-test == 'test-same-version-module-creation'}} + run: | + echo $MODULE_TEMPLATE_PATH + make -C tests/e2e test-same-version-module-creation \ No newline at end of file diff --git a/pkg/module/remote.go b/pkg/module/remote.go index cf3ba0431..b7a6a500d 100644 --- a/pkg/module/remote.go +++ b/pkg/module/remote.go @@ -136,6 +136,16 @@ func (r *Remote) Push(archive *comparch.ComponentArchive, overwrite bool) (ocm.C return nil, err } + if !overwrite { + versionAlreadyExists, _ := repo.ExistsComponentVersion( + archive.ComponentVersionAccess.GetName(), archive.ComponentVersionAccess.GetVersion(), + ) + + if versionAlreadyExists { + return nil, fmt.Errorf("version %s already exists", archive.ComponentVersionAccess.GetVersion()) + } + } + transferHandler, err := standard.New(standard.Overwrite(overwrite)) if err != nil { return nil, fmt.Errorf("could not setup archive transfer: %w", err) diff --git a/tests/e2e/Makefile b/tests/e2e/Makefile index c30ce8d41..3eed76896 100644 --- a/tests/e2e/Makefile +++ b/tests/e2e/Makefile @@ -35,6 +35,10 @@ help: ## Display this help. test-module-creation: go test ./create_module -run "Test_ModuleTemplate" +.PHONY: test-same-version-module-creation +test-same-version-module-creation: + go test ./create_module -run "Test_SameVersion_ModuleCreation" + .PHONY: test-module-enabling-disabling test-module-enabling-disabling: go test -ginkgo.v -ginkgo.focus "Kyma CLI deploy, enable and disable commands usage" \ No newline at end of file diff --git a/tests/e2e/create_module/kyma_create_module_same_version_test.go b/tests/e2e/create_module/kyma_create_module_same_version_test.go new file mode 100644 index 000000000..3a5cb1cbd --- /dev/null +++ b/tests/e2e/create_module/kyma_create_module_same_version_test.go @@ -0,0 +1,25 @@ +package create_module_test + +import ( + "testing" + + "github.com/kyma-project/cli/tests/e2e" + "github.com/stretchr/testify/assert" +) + +func Test_SameVersion_ModuleCreation(t *testing.T) { + path := "../../../template-operator" + registry := "http://k3d-oci.localhost:5001" + configFilePath := "../../../template-operator/module-config.yaml" + version := "v1.0.0" + + t.Run("Create same version module with module-archive-version-overwrite flag", func(t *testing.T) { + err := e2e.CreateModuleCommand(true, path, registry, configFilePath, version) + assert.Nil(t, err) + }) + + t.Run("Create same version module without module-archive-version-overwrite flag", func(t *testing.T) { + err := e2e.CreateModuleCommand(false, path, registry, configFilePath, version) + assert.Equal(t, e2e.ErrCreateModuleFailedWithSameVersion, err) + }) +} diff --git a/tests/e2e/util.go b/tests/e2e/util.go index d6525143b..875f08ed4 100644 --- a/tests/e2e/util.go +++ b/tests/e2e/util.go @@ -18,10 +18,12 @@ import ( ) var ( - errKymaDeployCommandFailed = errors.New("failed to run kyma alpha deploy") - errModuleTemplateNotApplied = errors.New("failed to apply ModuleTemplate") - errModuleEnablingFailed = errors.New("failed to enable module") - errModuleDisablingFailed = errors.New("failed to disable module") + errKymaDeployCommandFailed = errors.New("failed to run kyma alpha deploy") + errModuleTemplateNotApplied = errors.New("failed to apply ModuleTemplate") + errModuleEnablingFailed = errors.New("failed to enable module") + errModuleDisablingFailed = errors.New("failed to disable module") + ErrCreateModuleFailedWithSameVersion = errors.New( + "failed to create module with same version exists message") ) const ( @@ -207,3 +209,25 @@ func Flatten(labels v1.Labels) map[string]string { return labelsMap } + +func CreateModuleCommand(versionOverwrite bool, path, registry, configFilePath, version string) error { + var createModuleCmd *exec.Cmd + if versionOverwrite { + createModuleCmd = exec.Command("kyma", "alpha", "create", "module", + "--path", path, "--registry", registry, "--insecure", "--module-config-file", configFilePath, + "--version", version, "--module-archive-version-overwrite") + } else { + createModuleCmd = exec.Command("kyma", "alpha", "create", "module", + "--path", path, "--registry", registry, "--insecure", "--module-config-file", configFilePath, + "--version", version) + } + createOut, err := createModuleCmd.CombinedOutput() + + if err != nil { + if strings.Contains(string(createOut), fmt.Sprintf("version %s already exists", version)) { + return ErrCreateModuleFailedWithSameVersion + } + return fmt.Errorf("create module command failed with err %s", err) + } + return nil +} From dd6255717d55c58e6d28290dc238ff5954aad078 Mon Sep 17 00:00:00 2001 From: Nesma Badr Date: Mon, 9 Oct 2023 19:14:31 +0200 Subject: [PATCH 04/10] fix: Add module version annotation to the ModuleTemplate (#1799) * add test * Addressing test comment * PR comments --- cmd/kyma/alpha/create/module/module.go | 61 ++++--- cmd/kyma/alpha/create/module/module_test.go | 162 ++++++++++++++++++ pkg/module/validation.go | 6 +- .../create_module/kyma_create_module_test.go | 9 +- 4 files changed, 212 insertions(+), 26 deletions(-) diff --git a/cmd/kyma/alpha/create/module/module.go b/cmd/kyma/alpha/create/module/module.go index 3e9f15aa4..65a2a95d0 100644 --- a/cmd/kyma/alpha/create/module/module.go +++ b/cmd/kyma/alpha/create/module/module.go @@ -4,10 +4,12 @@ import ( "context" "errors" "fmt" + "maps" "os" "path/filepath" "strings" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/mandelsoft/vfs/pkg/memoryfs" "github.com/mandelsoft/vfs/pkg/osfs" "github.com/mandelsoft/vfs/pkg/vfs" @@ -16,7 +18,6 @@ import ( "github.com/open-component-model/ocm/pkg/contexts/ocm/repositories/comparch" "github.com/spf13/cobra" "go.uber.org/zap" - "golang.org/x/exp/maps" "gopkg.in/yaml.v3" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" @@ -382,29 +383,9 @@ func (cmd *command) Run(ctx context.Context) error { cmd.NewStep("Generating module template") - labels := map[string]string{} - annotations := map[string]string{} - var resourceName = "" - if modCnf != nil { resourceName = modCnf.ResourceName - - maps.Copy(labels, modCnf.Labels) - maps.Copy(annotations, modCnf.Annotations) - - if modCnf.Beta { - labels["operator.kyma-project.io/beta"] = "true" - } - if modCnf.Internal { - labels["operator.kyma-project.io/internal"] = "true" - } - } - isClusterScoped := isCrdClusterScoped(crValidator.GetCrd()) - if isClusterScoped { - annotations["operator.kyma-project.io/is-cluster-scoped"] = "true" - } else { - annotations["operator.kyma-project.io/is-cluster-scoped"] = "false" } var channel = cmd.opts.Channel @@ -417,6 +398,9 @@ func (cmd *command) Run(ctx context.Context) error { namespace = modCnf.Namespace } + labels := cmd.getModuleTemplateLabels(modCnf) + annotations := cmd.getModuleTemplateAnnotations(modCnf, crValidator) + t, err := module.Template(componentVersionAccess, resourceName, namespace, channel, modDef.DefaultCR, labels, annotations, modDef.CustomStateChecks) @@ -435,6 +419,41 @@ func (cmd *command) Run(ctx context.Context) error { return nil } +func (cmd *command) getModuleTemplateLabels(modCnf *Config) map[string]string { + labels := map[string]string{} + if modCnf != nil { + maps.Copy(labels, modCnf.Labels) + + if modCnf.Beta { + labels[v1beta2.BetaLabel] = v1beta2.EnableLabelValue + } + if modCnf.Internal { + labels[v1beta2.InternalLabel] = v1beta2.EnableLabelValue + } + } + + return labels +} + +func (cmd *command) getModuleTemplateAnnotations(modCnf *Config, crValidator validator) map[string]string { + annotations := map[string]string{} + moduleVersion := cmd.opts.Version + if modCnf != nil { + maps.Copy(annotations, modCnf.Annotations) + + moduleVersion = modCnf.Version + } + + isClusterScoped := isCrdClusterScoped(crValidator.GetCrd()) + if isClusterScoped { + annotations[v1beta2.IsClusterScopedAnnotation] = v1beta2.EnableLabelValue + } else { + annotations[v1beta2.IsClusterScopedAnnotation] = v1beta2.DisableLabelValue + } + annotations["operator.kyma-project.io/module-version"] = moduleVersion + return annotations +} + func (cmd *command) validateDefaultCR(ctx context.Context, modDef *module.Definition, l *zap.SugaredLogger) (validator, error) { cmd.NewStep("Validating Default CR") diff --git a/cmd/kyma/alpha/create/module/module_test.go b/cmd/kyma/alpha/create/module/module_test.go index b62fa5142..82d5ec970 100644 --- a/cmd/kyma/alpha/create/module/module_test.go +++ b/cmd/kyma/alpha/create/module/module_test.go @@ -2,7 +2,12 @@ package module import ( _ "embed" + "reflect" "testing" + + "github.com/kyma-project/cli/internal/cli" + "github.com/kyma-project/cli/pkg/module" + "github.com/kyma-project/lifecycle-manager/api/v1beta2" ) //go:embed testdata/clusterScopedCRD.yaml @@ -43,3 +48,160 @@ func Test_isCrdClusterScoped(t *testing.T) { }) } } + +func Test_command_getModuleTemplateLabels(t *testing.T) { + type fields struct { + Command cli.Command + opts *Options + } + type args struct { + modCnf *Config + } + tests := []struct { + name string + fields fields + args args + want map[string]string + }{ + { + name: "beta module with moduleConfig labels set", + fields: fields{ + opts: &Options{}, + }, + args: args{ + modCnf: &Config{ + Beta: true, + Labels: map[string]string{ + "label1": "value1", + "label2": "value2", + }, + Version: "1.1.1", + }, + }, + want: map[string]string{ + "label1": "value1", + "label2": "value2", + v1beta2.BetaLabel: v1beta2.EnableLabelValue, + }, + }, + { + name: "internal module", + fields: fields{ + opts: &Options{}, + }, + args: args{ + modCnf: &Config{ + Internal: true, + Version: "1.1.1", + }, + }, + want: map[string]string{ + v1beta2.InternalLabel: v1beta2.EnableLabelValue, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &command{ + Command: tt.fields.Command, + opts: tt.fields.opts, + } + if got := cmd.getModuleTemplateLabels(tt.args.modCnf); !reflect.DeepEqual(got, tt.want) { + t.Errorf("getModuleTemplateLabels() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_command_getModuleTemplateAnnotations(t *testing.T) { + type fields struct { + Command cli.Command + opts *Options + } + type args struct { + modCnf *Config + crValidator validator + } + tests := []struct { + name string + fields fields + args args + want map[string]string + }{ + { + name: "module with moduleConfig annotations set", + fields: fields{ + opts: &Options{}, + }, + args: args{ + modCnf: &Config{ + Internal: true, + Annotations: map[string]string{ + "annotation1": "value1", + "annotation2": "value2", + }, + Version: "1.1.1", + }, + crValidator: &module.SingleManifestFileCRValidator{ + Crd: namespacedScopedCrd, + }, + }, + want: map[string]string{ + "annotation1": "value1", + "annotation2": "value2", + "operator.kyma-project.io/module-version": "1.1.1", + v1beta2.IsClusterScopedAnnotation: v1beta2.DisableLabelValue, + }, + }, + { + name: "cluster scoped module with moduleConfig annotations set", + fields: fields{ + opts: &Options{}, + }, + args: args{ + modCnf: &Config{ + Annotations: map[string]string{ + "annotation1": "value1", + "annotation2": "value2", + }, + Version: "1.1.1", + }, + crValidator: &module.SingleManifestFileCRValidator{ + Crd: clusterScopedCrd, + }, + }, + want: map[string]string{ + "annotation1": "value1", + "annotation2": "value2", + v1beta2.IsClusterScopedAnnotation: v1beta2.EnableLabelValue, + "operator.kyma-project.io/module-version": "1.1.1", + }, + }, + { + name: "module versions set from version flag", + fields: fields{ + opts: &Options{Version: "1.0.0"}, + }, + args: args{ + crValidator: &module.SingleManifestFileCRValidator{ + Crd: namespacedScopedCrd, + }, + }, + want: map[string]string{ + "operator.kyma-project.io/module-version": "1.0.0", + v1beta2.IsClusterScopedAnnotation: v1beta2.DisableLabelValue, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &command{ + Command: tt.fields.Command, + opts: tt.fields.opts, + } + if got := cmd.getModuleTemplateAnnotations(tt.args.modCnf, tt.args.crValidator); !reflect.DeepEqual(got, tt.want) { + t.Errorf("getModuleTemplateAnnotations() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/module/validation.go b/pkg/module/validation.go index c13cc9b13..9a1b5446d 100644 --- a/pkg/module/validation.go +++ b/pkg/module/validation.go @@ -356,7 +356,7 @@ func ValidateName(name string) error { type SingleManifestFileCRValidator struct { manifestPath string crData []byte - crd []byte + Crd []byte } func NewSingleManifestFileCRValidator(cr []byte, manifestPath string) *SingleManifestFileCRValidator { @@ -390,7 +390,7 @@ func (v *SingleManifestFileCRValidator) Run(ctx context.Context, log *zap.Sugare if crdBytes == nil { return fmt.Errorf("can't find the CRD for (group: %q, kind %q)", group, kind) } - v.crd = crdBytes + v.Crd = crdBytes // store extracted CRD in a temp file tempDir, err := os.MkdirTemp("", "temporary-crd") @@ -414,7 +414,7 @@ func (v *SingleManifestFileCRValidator) Run(ctx context.Context, log *zap.Sugare } func (v *SingleManifestFileCRValidator) GetCrd() []byte { - return v.crd + return v.Crd } func (v *DefaultCRValidator) GetCrd() []byte { diff --git a/tests/e2e/create_module/kyma_create_module_test.go b/tests/e2e/create_module/kyma_create_module_test.go index 3afd58025..e6c8e0322 100644 --- a/tests/e2e/create_module/kyma_create_module_test.go +++ b/tests/e2e/create_module/kyma_create_module_test.go @@ -19,7 +19,6 @@ import ( ) func Test_ModuleTemplate(t *testing.T) { - moduleTemplateVersion := os.Getenv("MODULE_TEMPLATE_VERSION") ociRepoURL := os.Getenv("OCI_REPOSITORY_URL") testRepoURL := os.Getenv("TEST_REPOSITORY_URL") @@ -29,6 +28,12 @@ func Test_ModuleTemplate(t *testing.T) { assert.Nil(t, err) assert.Equal(t, descriptor.SchemaVersion(), v2.SchemaVersion) + // test annotations + annotations := template.Annotations + expectedModuleTemplateVersion := os.Getenv("MODULE_TEMPLATE_VERSION") + assert.Equal(t, annotations["operator.kyma-project.io/module-version"], expectedModuleTemplateVersion) + assert.Equal(t, annotations["operator.kyma-project.io/is-cluster-scoped"], "false") + // test descriptor.component.repositoryContexts assert.Equal(t, len(descriptor.RepositoryContexts), 1) unstructuredRepo := descriptor.GetEffectiveRepositoryContext() @@ -46,7 +51,7 @@ func Test_ModuleTemplate(t *testing.T) { assert.Equal(t, resource.Name, module.RawManifestLayerName) assert.Equal(t, resource.Relation, ocmMetaV1.LocalRelation) assert.Equal(t, resource.Type, module.TypeYaml) - assert.Equal(t, resource.Version, moduleTemplateVersion) + assert.Equal(t, resource.Version, expectedModuleTemplateVersion) // test descriptor.component.resources[0].access resourceAccessSpec, err := ocm.DefaultContext().AccessSpecForSpec(resource.Access) From 1a8b461ccaf61a54d69cbacb31b3f629a1102283 Mon Sep 17 00:00:00 2001 From: Nesma Badr Date: Tue, 10 Oct 2023 12:38:34 +0200 Subject: [PATCH 05/10] enhance message (#1801) --- pkg/module/remote.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/module/remote.go b/pkg/module/remote.go index b7a6a500d..f6dd261e5 100644 --- a/pkg/module/remote.go +++ b/pkg/module/remote.go @@ -142,7 +142,8 @@ func (r *Remote) Push(archive *comparch.ComponentArchive, overwrite bool) (ocm.C ) if versionAlreadyExists { - return nil, fmt.Errorf("version %s already exists", archive.ComponentVersionAccess.GetVersion()) + return nil, fmt.Errorf("version %s already exists, please use --module-archive-version-overwrite "+ + "flag to overwrite it", archive.ComponentVersionAccess.GetVersion()) } } From 8cf17fdb4330804dbc6baaefcefc126c165488e4 Mon Sep 17 00:00:00 2001 From: Benjamin Lindner <50365642+lindnerby@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:12:32 +0200 Subject: [PATCH 06/10] feat: Add refactor title type (#1803) --- .github/workflows/lint-conventional-prs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint-conventional-prs.yml b/.github/workflows/lint-conventional-prs.yml index 9857482c6..ecc317dd0 100644 --- a/.github/workflows/lint-conventional-prs.yml +++ b/.github/workflows/lint-conventional-prs.yml @@ -19,11 +19,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: types: | - deps chore + deps docs feat fix + refactor test requireScope: false # https://regex101.com/r/YybDgS/1 From dea269075b389685a99504e79251c712a4816068 Mon Sep 17 00:00:00 2001 From: Benjamin Lindner <50365642+lindnerby@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:48:32 +0200 Subject: [PATCH 07/10] remove custom multierror. use join on one fix occurence (#1802) --- internal/kube/ssa.go | 3 +- pkg/errs/multierror.go | 62 ------------------------------------- pkg/errs/multierror_test.go | 26 ---------------- 3 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 pkg/errs/multierror.go delete mode 100644 pkg/errs/multierror_test.go diff --git a/internal/kube/ssa.go b/internal/kube/ssa.go index fe633453f..d39979e99 100644 --- a/internal/kube/ssa.go +++ b/internal/kube/ssa.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - "github.com/kyma-project/cli/pkg/errs" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -59,7 +58,7 @@ func (c *ConcurrentDefaultSSA) Run(ctx context.Context, resources []*resource.In ssaFinish := time.Since(ssaStart) if errsFromApply != nil { - return fmt.Errorf("ServerSideApply failed (after %s): %w", ssaFinish, errs.MergeErrors(errsFromApply...)) + return fmt.Errorf("ServerSideApply failed (after %s): %w", ssaFinish, errors.Join(errsFromApply...)) } logger.V(2).Info("ServerSideApply finished", "time", ssaFinish) return nil diff --git a/pkg/errs/multierror.go b/pkg/errs/multierror.go deleted file mode 100644 index 430f70d63..000000000 --- a/pkg/errs/multierror.go +++ /dev/null @@ -1,62 +0,0 @@ -package errs - -import ( - "errors" - "fmt" - "strings" -) - -type Multierror []error - -// As attempts to find the first error in the error list that matches the type -// of the value that target points to. -// -// This function allows errors.As to traverse the values stored on the -// multierr error. -func (merr Multierror) As(target interface{}) bool { - for _, err := range merr { - if errors.As(err, target) { - return true - } - } - return false -} - -// Is attempts to match the provided error against errors in the error list. -// -// This function allows errors.Is to traverse the values stored on the -// multierr error. -func (merr Multierror) Is(target error) bool { - for _, err := range merr { - if errors.Is(err, target) { - return true - } - } - return false -} - -func (merr Multierror) Error() string { - buf := strings.Builder{} - for _, e := range merr { - buf.WriteString(fmt.Sprintf("%s\n", e)) - } - return buf.String() -} - -// MergeErrs checks all errors passed and merges all non-nil errors into a MultiError -// if no errors are passed or all are nil, this function returns nil -func MergeErrors(errSlice ...error) error { - res := Multierror{} - - for _, e := range errSlice { - if e != nil { - res = append(res, e) - } - } - - if len(res) > 0 { - return res - } - - return nil -} diff --git a/pkg/errs/multierror_test.go b/pkg/errs/multierror_test.go deleted file mode 100644 index 5c5c19f4d..000000000 --- a/pkg/errs/multierror_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package errs - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestMergeErrors(t *testing.T) { - t.Parallel() - - // No errors passed -> nil - res := MergeErrors() - require.Nil(t, res, "MergeErrors should return nil when no parameters are received.") - - // Nil errors passed -> nil - res = MergeErrors(nil, nil) - require.Nil(t, res, "MergeErrors should return nil when all errors passed are nil.") - - // happy path - res = MergeErrors(errors.New("Error 1"), errors.New("Error 2"), nil) - require.NotNil(t, res, "MergeErrors should not return nil when at least one non-nil error is passed.") - require.Len(t, res, 2, "MergeErrors should return a length 2 Multierror, ignoring nil errors.") - require.Equal(t, res.Error(), "Error 1\nError 2\n", "Multierror format not as expected") -} From e4e44519d703d8cc49104399cbb4e6d44a2d8aed Mon Sep 17 00:00:00 2001 From: Benjamin Lindner <50365642+lindnerby@users.noreply.github.com> Date: Tue, 17 Oct 2023 10:41:00 +0200 Subject: [PATCH 08/10] chore: Fix some CLI checkmarx issues (#1807) * Add some error handling * More error handling for regex * Condest reconciler call * Add default status --- cmd/kyma/alpha/create/module/moduleconfig.go | 15 ++++++++--- cmd/kyma/alpha/create/module/opts.go | 6 +++-- internal/deploy/deploy.go | 26 ++++++++++---------- pkg/module/blob/blob.go | 8 ++++-- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/cmd/kyma/alpha/create/module/moduleconfig.go b/cmd/kyma/alpha/create/module/moduleconfig.go index 593a974b8..5f70915ec 100644 --- a/cmd/kyma/alpha/create/module/moduleconfig.go +++ b/cmd/kyma/alpha/create/module/moduleconfig.go @@ -89,7 +89,10 @@ func (cv *configValidator) validateName() *configValidator { if len(cv.config.Name) > moduleNameMaxLen { return fmt.Errorf("%w, module name length cannot exceed 255 characters", ErrNameValidation) } - matched, _ := regexp.MatchString(moduleNamePattern, cv.config.Name) + matched, err := regexp.MatchString(moduleNamePattern, cv.config.Name) + if err != nil { + return fmt.Errorf("failed to evaluate regex for module name pattern: %w", err) + } if !matched { return fmt.Errorf("%w for input %q, name must match the required pattern, e.g: 'github.com/path-to/your-repo'", ErrNameValidation, cv.config.Name) } @@ -108,7 +111,10 @@ func (cv *configValidator) validateNamespace() *configValidator { if len(cv.config.Namespace) > namespaceMaxLen { return fmt.Errorf("%w, module name length cannot exceed 253 characters", ErrNamespaceValidation) } - matched, _ := regexp.MatchString(namespacePattern, cv.config.Namespace) + matched, err := regexp.MatchString(namespacePattern, cv.config.Namespace) + if err != nil { + return fmt.Errorf("failed to evaluate regex for module namespace pattern: %w", err) + } if !matched { return fmt.Errorf("%w for input %q, namespace must contain only small alphanumeric characters and hyphens", ErrNamespaceValidation, cv.config.Namespace) } @@ -155,7 +161,10 @@ func (cv *configValidator) validateChannel() *configValidator { "%w for input %q, invalid channel length, length should between %d and %d", ErrChannelValidation, cv.config.Channel, ChannelMinLength, ChannelMaxLength) } - matched, _ := regexp.MatchString(`^[a-z]+$`, cv.config.Channel) + matched, err := regexp.MatchString(`^[a-z]+$`, cv.config.Channel) + if err != nil { + return fmt.Errorf("failed to evaluate regex for channel: %w", err) + } if !matched { return fmt.Errorf("%w for input %q, invalid channel format, only allow characters from a-z", ErrChannelValidation, cv.config.Channel) } diff --git a/cmd/kyma/alpha/create/module/opts.go b/cmd/kyma/alpha/create/module/opts.go index 60900f7da..52c16254d 100644 --- a/cmd/kyma/alpha/create/module/opts.go +++ b/cmd/kyma/alpha/create/module/opts.go @@ -92,14 +92,16 @@ func (o *Options) validatePath() error { } func (o *Options) validateChannel() error { - if len(o.Channel) < ChannelMinLength || len(o.Channel) > ChannelMaxLength { return fmt.Errorf( "invalid channel length, length should between %d and %d, %w", ChannelMinLength, ChannelMaxLength, ErrChannelValidation, ) } - matched, _ := regexp.MatchString(`^[a-z]+$`, o.Channel) + matched, err := regexp.MatchString(`^[a-z]+$`, o.Channel) + if err != nil { + return fmt.Errorf("failed to evaluate regex for channel: %w", err) + } if !matched { return fmt.Errorf("invalid channel format, only allow characters from a-z") } diff --git a/internal/deploy/deploy.go b/internal/deploy/deploy.go index 9eaab04b6..c840b26a2 100644 --- a/internal/deploy/deploy.go +++ b/internal/deploy/deploy.go @@ -73,33 +73,33 @@ func doReconciliation(opts Options, delete bool) (*service.ReconciliationResult, } manifests := make(chan ComponentStatus) - runtimeBuilder := service.NewRuntimeBuilder(reconciliation.NewInMemoryReconciliationRepository(), opts.Logger) - reconcilationResult, err := runtimeBuilder.RunLocal(func(component string, msg *reconciler.CallbackMessage) { - var state ComponentState - var errorRecieved error + statusFunc := func(component string, msg *reconciler.CallbackMessage) { + status := ComponentStatus{component, "", nil, msg.Manifest} switch msg.Status { case reconciler.StatusSuccess: - state = Success - errorRecieved = nil + status = ComponentStatus{component, Success, nil, msg.Manifest} case reconciler.StatusFailed: - errorRecieved = errors.Errorf("%s", msg.Error) - state = RecoverableError + status = ComponentStatus{component, + RecoverableError, + errors.Errorf("%s", msg.Error), + msg.Manifest} case reconciler.StatusError: - errorRecieved = errors.Errorf("%s", msg.Error) - state = UnrecoverableError + status = ComponentStatus{component, + UnrecoverableError, + errors.Errorf("%s", msg.Error), + msg.Manifest} } - status := ComponentStatus{component, state, errorRecieved, msg.Manifest} - if opts.DryRun { go manifestCollector(manifests) manifests <- status } opts.StatusFunc(status) + } - }). + reconcilationResult, err := runtimeBuilder.RunLocal(statusFunc). WithSchedulerConfig(&service.SchedulerConfig{ PreComponents: opts.Components.PrerequisiteNames(), DeleteStrategy: ds, diff --git a/pkg/module/blob/blob.go b/pkg/module/blob/blob.go index 878a59024..253a2e5fe 100644 --- a/pkg/module/blob/blob.go +++ b/pkg/module/blob/blob.go @@ -346,8 +346,12 @@ func addFileToTar( return fmt.Errorf("unable to open file %q: %w", path, err) } if _, err := io.Copy(tw, file); err != nil { - _ = file.Close() - return fmt.Errorf("unable to add file to tar %q: %w", path, err) + copyErr := err + err = file.Close() + if err != nil { + return fmt.Errorf("unable to close file %q: %w", path, err) + } + return fmt.Errorf("unable to add file to tar %q: %w", path, copyErr) } if err := file.Close(); err != nil { return fmt.Errorf("unable to close file %q: %w", path, err) From 360c4aeab4b5da9346f2a7a887d8fabbfa61f73a Mon Sep 17 00:00:00 2001 From: Nesma Badr Date: Mon, 23 Oct 2023 11:27:30 +0200 Subject: [PATCH 09/10] bump golang.org/x/net (#1815) --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 447e48d60..dca044be9 100644 --- a/go.mod +++ b/go.mod @@ -248,13 +248,13 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.13.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect diff --git a/go.sum b/go.sum index 64cb4a4e5..ab98370ff 100644 --- a/go.sum +++ b/go.sum @@ -1834,8 +1834,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1961,8 +1961,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2127,8 +2127,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2139,8 +2139,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From ae3e63bfc02602964d75e8cb6c0d453038d28cce Mon Sep 17 00:00:00 2001 From: Jeremy Harisch <48282931+jeremyharisch@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:27:29 +0200 Subject: [PATCH 10/10] fix(checkmarx): Fix unhandled errors (#1813) * Fix unhandled errors * APlly review comments * fix misspelling --- cmd/kyma/alpha/list/module/opts.go | 5 ++++- cmd/kyma/apply/function/function.go | 6 +++++- cmd/kyma/apply/function/opts.go | 9 ++++++--- internal/k3d/k3d.go | 10 ++++++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/cmd/kyma/alpha/list/module/opts.go b/cmd/kyma/alpha/list/module/opts.go index 396d83a41..485f7dbc6 100644 --- a/cmd/kyma/alpha/list/module/opts.go +++ b/cmd/kyma/alpha/list/module/opts.go @@ -88,7 +88,10 @@ func (o *Options) validateChannel() error { ChannelMinLength, ChannelMaxLength, ErrChannelValidation, ) } - matched, _ := regexp.MatchString(`^[a-z]+$`, o.Channel) + matched, err := regexp.MatchString(`^[a-z]+$`, o.Channel) + if err != nil { + return fmt.Errorf("failed to evaluate regex for channel: %w", err) + } if !matched { return fmt.Errorf("invalid channel format, only allow characters from a-z") } diff --git a/cmd/kyma/apply/function/function.go b/cmd/kyma/apply/function/function.go index ff5ac15a1..0f96b26ce 100644 --- a/cmd/kyma/apply/function/function.go +++ b/cmd/kyma/apply/function/function.go @@ -64,7 +64,11 @@ Use the flags to specify the desired location for the source files or run the co func (c *command) Run() error { if c.opts.Filename == "" { - c.opts.Filename = defaultFilename() + filename, err := defaultFilename() + if err != nil { + return fmt.Errorf("failed to create default filename: %w", err) + } + c.opts.Filename = filename } if c.opts.Output.value == "yaml" { diff --git a/cmd/kyma/apply/function/opts.go b/cmd/kyma/apply/function/opts.go index ac15f7eec..519ba6862 100644 --- a/cmd/kyma/apply/function/opts.go +++ b/cmd/kyma/apply/function/opts.go @@ -98,7 +98,10 @@ func (g value) Type() string { return "value" } -func defaultFilename() string { - pwd, _ := os.Getwd() - return path.Join(pwd, workspace.CfgFilename) +func defaultFilename() (string, error) { + pwd, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("failed to get current working directory: %w", err) + } + return path.Join(pwd, workspace.CfgFilename), nil } diff --git a/internal/k3d/k3d.go b/internal/k3d/k3d.go index f5de2052c..0d7ab9eec 100644 --- a/internal/k3d/k3d.go +++ b/internal/k3d/k3d.go @@ -92,7 +92,10 @@ func (c *client) checkVersion() error { return err } - exp, _ := regexp.Compile(fmt.Sprintf(`%s version v([^\s-]+)`, binaryName)) + exp, err := regexp.Compile(fmt.Sprintf(`%s version v([^\s-]+)`, binaryName)) + if err != nil { + return fmt.Errorf("failed to evaluate regex for version naming schema: %w", err) + } binaryVersion := exp.FindStringSubmatch(binaryVersionOutput) if c.verbose { fmt.Printf("Extracted %s version: '%s'", binaryName, binaryVersion[1]) @@ -105,7 +108,10 @@ func (c *client) checkVersion() error { return err } - minRequiredSemVersion, _ := semver.Parse(minRequiredVersion) + minRequiredSemVersion, err := semver.Parse(minRequiredVersion) + if err != nil { + return fmt.Errorf("failed to parse semantic version: %w", err) + } if binarySemVersion.Major > minRequiredSemVersion.Major { incompatibleMajorVersionMsg := "You are using an unsupported k3d major version '%d'. The supported k3d major version for this command is '%d'." return fmt.Errorf(incompatibleMajorVersionMsg, binarySemVersion.Major, minRequiredSemVersion.Major)