You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	kubernetesDeploy - fix & updates (#1926)
* kubernetesDeploy - updates * add debugging output * fix type checking * remove debugging output * fix secret info * fix tests * Update vars/commonPipelineEnvironment.groovy Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com> * Update vars/commonPipelineEnvironment.groovy Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>
This commit is contained in:
		| @@ -71,42 +71,48 @@ func runHelmDeploy(config kubernetesDeployOptions, command command.ExecRunner, s | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var dockerRegistrySecret bytes.Buffer | ||||
| 	command.Stdout(&dockerRegistrySecret) | ||||
| 	kubeParams := []string{ | ||||
| 		"--insecure-skip-tls-verify=true", | ||||
| 		"create", | ||||
| 		"secret", | ||||
| 		"docker-registry", | ||||
| 		"regsecret", | ||||
| 		fmt.Sprintf("--docker-server=%v", containerRegistry), | ||||
| 		fmt.Sprintf("--docker-username=%v", config.ContainerRegistryUser), | ||||
| 		fmt.Sprintf("--docker-password=%v", config.ContainerRegistryPassword), | ||||
| 		"--dry-run=true", | ||||
| 		"--output=json", | ||||
| 	} | ||||
| 	log.Entry().Infof("Calling kubectl create secret --dry-run=true ...") | ||||
| 	log.Entry().Debugf("kubectl parameters %v", kubeParams) | ||||
| 	if err := command.RunExecutable("kubectl", kubeParams...); err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Retrieving Docker config via kubectl failed") | ||||
| 	} | ||||
| 	log.Entry().Debugf("Secret created: %v", string(dockerRegistrySecret.Bytes())) | ||||
| 	var secretsData string | ||||
| 	if len(config.ContainerRegistryUser) == 0 || len(config.ContainerRegistryPassword) == 0 { | ||||
| 		log.Entry().Info("No container registry credentials provided or credentials incomplete: skipping secret creation") | ||||
| 		secretsData = fmt.Sprintf(",imagePullSecrets[0].name=%v", config.ContainerRegistrySecret) | ||||
| 	} else { | ||||
| 		var dockerRegistrySecret bytes.Buffer | ||||
| 		command.Stdout(&dockerRegistrySecret) | ||||
| 		kubeParams := []string{ | ||||
| 			"--insecure-skip-tls-verify=true", | ||||
| 			"create", | ||||
| 			"secret", | ||||
| 			"docker-registry", | ||||
| 			config.ContainerRegistrySecret, | ||||
| 			fmt.Sprintf("--docker-server=%v", containerRegistry), | ||||
| 			fmt.Sprintf("--docker-username=%v", config.ContainerRegistryUser), | ||||
| 			fmt.Sprintf("--docker-password=%v", config.ContainerRegistryPassword), | ||||
| 			"--dry-run=true", | ||||
| 			"--output=json", | ||||
| 		} | ||||
| 		log.Entry().Infof("Calling kubectl create secret --dry-run=true ...") | ||||
| 		log.Entry().Debugf("kubectl parameters %v", kubeParams) | ||||
| 		if err := command.RunExecutable("kubectl", kubeParams...); err != nil { | ||||
| 			log.Entry().WithError(err).Fatal("Retrieving Docker config via kubectl failed") | ||||
| 		} | ||||
| 		log.Entry().Debugf("Secret created: %v", string(dockerRegistrySecret.Bytes())) | ||||
|  | ||||
| 	var dockerRegistrySecretData struct { | ||||
| 		Kind string `json:"kind"` | ||||
| 		Data struct { | ||||
| 			DockerConfJSON string `json:".dockerconfigjson"` | ||||
| 		} `json:"data"` | ||||
| 		Type string `json:"type"` | ||||
| 	} | ||||
| 	if err := json.Unmarshal(dockerRegistrySecret.Bytes(), &dockerRegistrySecretData); err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Reading docker registry secret json failed") | ||||
| 	} | ||||
| 	// make sure that secret is hidden in log output | ||||
| 	log.RegisterSecret(dockerRegistrySecretData.Data.DockerConfJSON) | ||||
| 		var dockerRegistrySecretData struct { | ||||
| 			Kind string `json:"kind"` | ||||
| 			Data struct { | ||||
| 				DockerConfJSON string `json:".dockerconfigjson"` | ||||
| 			} `json:"data"` | ||||
| 			Type string `json:"type"` | ||||
| 		} | ||||
| 		if err := json.Unmarshal(dockerRegistrySecret.Bytes(), &dockerRegistrySecretData); err != nil { | ||||
| 			log.Entry().WithError(err).Fatal("Reading docker registry secret json failed") | ||||
| 		} | ||||
| 		// make sure that secret is hidden in log output | ||||
| 		log.RegisterSecret(dockerRegistrySecretData.Data.DockerConfJSON) | ||||
|  | ||||
| 	// pass secret in helm default template way and in Piper backward compatible way | ||||
| 	secretsData := fmt.Sprintf("secret.dockerconfigjson=%v,imagePullSecrets[0].name=regsecret,imagePullSecrets[0].dockerconfigjson=%v", dockerRegistrySecretData.Data.DockerConfJSON, dockerRegistrySecretData.Data.DockerConfJSON) | ||||
| 		// pass secret in helm default template way and in Piper backward compatible way | ||||
| 		secretsData = fmt.Sprintf(",secret.name=%v,secret.dockerconfigjson=%v,imagePullSecrets[0].name=%v", config.ContainerRegistrySecret, dockerRegistrySecretData.Data.DockerConfJSON, config.ContainerRegistrySecret) | ||||
| 	} | ||||
|  | ||||
| 	ingressHosts := "" | ||||
| 	for i, h := range config.IngressHosts { | ||||
| @@ -121,7 +127,7 @@ func runHelmDeploy(config kubernetesDeployOptions, command command.ExecRunner, s | ||||
| 		"--force", | ||||
| 		"--namespace", config.Namespace, | ||||
| 		"--set", | ||||
| 		fmt.Sprintf("image.repository=%v/%v,image.tag=%v,%v%v", containerRegistry, containerImageName, containerImageTag, secretsData, ingressHosts), | ||||
| 		fmt.Sprintf("image.repository=%v/%v,image.tag=%v%v%v", containerRegistry, containerImageName, containerImageTag, secretsData, ingressHosts), | ||||
| 	} | ||||
|  | ||||
| 	if config.DeployTool == "helm" { | ||||
|   | ||||
| @@ -20,6 +20,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 			ContainerRegistryURL:      "https://my.registry:55555", | ||||
| 			ContainerRegistryUser:     "registryUser", | ||||
| 			ContainerRegistryPassword: "********", | ||||
| 			ContainerRegistrySecret:   "testSecret", | ||||
| 			ChartPath:                 "path/to/chart", | ||||
| 			DeploymentName:            "deploymentName", | ||||
| 			DeployTool:                "helm", | ||||
| @@ -35,7 +36,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
|  | ||||
| 		e := mock.ExecMockRunner{ | ||||
| 			StdoutReturn: map[string]string{ | ||||
| 				"kubectl --insecure-skip-tls-verify=true create secret docker-registry regsecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=******** --dry-run=true --output=json": dockerConfigJSON, | ||||
| 				`kubectl --insecure-skip-tls-verify=true create secret docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\* --dry-run=true --output=json`: dockerConfigJSON, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| @@ -47,7 +48,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 		assert.Equal(t, []string{"init", "--client-only"}, e.Calls[0].Params, "Wrong init parameters") | ||||
|  | ||||
| 		assert.Equal(t, "kubectl", e.Calls[1].Exec, "Wrong secret creation command") | ||||
| 		assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "regsecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.Calls[1].Params, "Wrong secret creation parameters") | ||||
| 		assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.Calls[1].Params, "Wrong secret creation parameters") | ||||
|  | ||||
| 		assert.Equal(t, "helm", e.Calls[2].Exec, "Wrong upgrade command") | ||||
| 		assert.Equal(t, []string{ | ||||
| @@ -59,7 +60,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 			"--namespace", | ||||
| 			"deploymentNamespace", | ||||
| 			"--set", | ||||
| 			"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=regsecret,imagePullSecrets[0].dockerconfigjson=ThisIsOurBase64EncodedSecret==,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", | ||||
| 			"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", | ||||
| 			"--wait", | ||||
| 			"--timeout", | ||||
| 			"400", | ||||
| @@ -75,6 +76,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 			ContainerRegistryURL:      "https://my.registry:55555", | ||||
| 			ContainerRegistryUser:     "registryUser", | ||||
| 			ContainerRegistryPassword: "********", | ||||
| 			ContainerRegistrySecret:   "testSecret", | ||||
| 			ChartPath:                 "path/to/chart", | ||||
| 			DeploymentName:            "deploymentName", | ||||
| 			DeployTool:                "helm3", | ||||
| @@ -90,7 +92,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
|  | ||||
| 		e := mock.ExecMockRunner{ | ||||
| 			StdoutReturn: map[string]string{ | ||||
| 				"kubectl --insecure-skip-tls-verify=true create secret docker-registry regsecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=******** --dry-run=true --output=json": dockerConfigJSON, | ||||
| 				`kubectl --insecure-skip-tls-verify=true create secret docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\* --dry-run=true --output=json`: dockerConfigJSON, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| @@ -99,7 +101,7 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 		runKubernetesDeploy(opts, &e, &stdout) | ||||
|  | ||||
| 		assert.Equal(t, "kubectl", e.Calls[0].Exec, "Wrong secret creation command") | ||||
| 		assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "regsecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.Calls[0].Params, "Wrong secret creation parameters") | ||||
| 		assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.Calls[0].Params, "Wrong secret creation parameters") | ||||
|  | ||||
| 		assert.Equal(t, "helm", e.Calls[1].Exec, "Wrong upgrade command") | ||||
| 		assert.Equal(t, []string{ | ||||
| @@ -111,7 +113,48 @@ func TestRunKubernetesDeploy(t *testing.T) { | ||||
| 			"--namespace", | ||||
| 			"deploymentNamespace", | ||||
| 			"--set", | ||||
| 			"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=regsecret,imagePullSecrets[0].dockerconfigjson=ThisIsOurBase64EncodedSecret==,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", | ||||
| 			"image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", | ||||
| 			"--atomic", | ||||
| 			"--timeout", | ||||
| 			"400s", | ||||
| 			"--kube-context", | ||||
| 			"testCluster", | ||||
| 			"--testParam", | ||||
| 			"testValue", | ||||
| 		}, e.Calls[1].Params, "Wrong upgrade parameters") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("test helm v3 - no container credentials", func(t *testing.T) { | ||||
| 		opts := kubernetesDeployOptions{ | ||||
| 			ContainerRegistryURL:    "https://my.registry:55555", | ||||
| 			ChartPath:               "path/to/chart", | ||||
| 			ContainerRegistrySecret: "testSecret", | ||||
| 			DeploymentName:          "deploymentName", | ||||
| 			DeployTool:              "helm3", | ||||
| 			HelmDeployWaitSeconds:   400, | ||||
| 			IngressHosts:            []string{"ingress.host1", "ingress.host2"}, | ||||
| 			Image:                   "path/to/Image:latest", | ||||
| 			AdditionalParameters:    []string{"--testParam", "testValue"}, | ||||
| 			KubeContext:             "testCluster", | ||||
| 			Namespace:               "deploymentNamespace", | ||||
| 		} | ||||
| 		e := mock.ExecMockRunner{} | ||||
|  | ||||
| 		var stdout bytes.Buffer | ||||
|  | ||||
| 		runKubernetesDeploy(opts, &e, &stdout) | ||||
|  | ||||
| 		assert.Equal(t, "helm", e.Calls[1].Exec, "Wrong upgrade command") | ||||
| 		assert.Equal(t, []string{ | ||||
| 			"upgrade", | ||||
| 			"deploymentName", | ||||
| 			"path/to/chart", | ||||
| 			"--install", | ||||
| 			"--force", | ||||
| 			"--namespace", | ||||
| 			"deploymentNamespace", | ||||
| 			"--set", | ||||
| 			"image.repository=my.registry:55555/path/to/Image,image.tag=latest,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", | ||||
| 			"--atomic", | ||||
| 			"--timeout", | ||||
| 			"400s", | ||||
|   | ||||
| @@ -229,6 +229,9 @@ spec: | ||||
|   containers: | ||||
|   - image: dtzar/helm-kubectl:3.1.2 | ||||
|     workingDir: /config | ||||
|     options: | ||||
|       - name: -u | ||||
|         value: '0' | ||||
|     conditions: | ||||
|     - conditionRef: strings-equal | ||||
|       params: | ||||
| @@ -236,6 +239,9 @@ spec: | ||||
|         value: helm3 | ||||
|   - image: dtzar/helm-kubectl:2.12.1 | ||||
|     workingDir: /config | ||||
|     options: | ||||
|       - name: -u | ||||
|         value: '0' | ||||
|     conditions: | ||||
|     - conditionRef: strings-equal | ||||
|       params: | ||||
| @@ -243,6 +249,9 @@ spec: | ||||
|         value: helm | ||||
|   - image: dtzar/helm-kubectl:2.12.1 | ||||
|     workingDir: /config | ||||
|     options: | ||||
|       - name: -u | ||||
|         value: '0' | ||||
|     conditions: | ||||
|     - conditionRef: strings-equal | ||||
|       params: | ||||
|   | ||||
| @@ -201,7 +201,7 @@ class commonPipelineEnvironment implements Serializable { | ||||
|         containerProperties.each({key, value -> | ||||
|             def fileName = ".pipeline/commonPipelineEnvironment/container/${key}" | ||||
|             if (value && !script.fileExists(fileName)) { | ||||
|                 if(value instanceof String) { | ||||
|                 if(value in CharSequence) { | ||||
|                     script.writeFile file: fileName, text: value | ||||
|                 } else { | ||||
|                     script.writeFile file: fileName, text: groovy.json.JsonOutput.toJson(value) | ||||
| @@ -212,7 +212,7 @@ class commonPipelineEnvironment implements Serializable { | ||||
|         valueMap.each({key, value -> | ||||
|             def fileName = ".pipeline/commonPipelineEnvironment/custom/${key}" | ||||
|             if (value && !script.fileExists(fileName)) { | ||||
|                 if(value instanceof String) { | ||||
|                 if(value in CharSequence) { | ||||
|                     script.writeFile file: fileName, text: value | ||||
|                 } else { | ||||
|                     script.writeFile file: fileName, text: groovy.json.JsonOutput.toJson(value) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user