1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-11-06 09:09:19 +02:00

feat (kubernetesDeploy) allow secret creation in cluster with kubectl as deploy tool (#3398)

* defaulting deocker config json location

* function change

* harmonising secret creation via json config apply

* adding the env path to kaniko

* env var

* adding path

* adding path

* adding path

* rolling back changes for path

* adapting condition for secret creation

* conditions based on username and password only

* fix unit test as per new secret creation

* update documentation with regards to secret creation

* fixing yaml lint empty line

* fixing trailing line from kaniko yaml

* error condition when path of the docker config json file is not found

Co-authored-by: anilkeshav27 <you@example.com>
This commit is contained in:
Anil Keshav
2022-01-11 11:30:40 +01:00
committed by GitHub
parent 78c4a8fe93
commit af6a1801ab
4 changed files with 235 additions and 274 deletions

View File

@@ -5,13 +5,15 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
piperDocker "github.com/SAP/jenkins-library/pkg/docker"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/docker"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
@@ -72,7 +74,7 @@ func runKubernetesDeploy(config kubernetesDeployOptions, utils kubernetesDeployU
if config.DeployTool == "helm" || config.DeployTool == "helm3" {
return runHelmDeploy(config, utils, stdout)
} else if config.DeployTool == "kubectl" {
return runKubectlDeploy(config, utils)
return runKubectlDeploy(config, utils, stdout)
}
return fmt.Errorf("Failed to execute deployments")
}
@@ -127,15 +129,18 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtils,
}
var secretsData string
if len(config.DockerConfigJSON) == 0 && (len(config.ContainerRegistryUser) == 0 || len(config.ContainerRegistryPassword) == 0) {
log.Entry().Info("No/incomplete container registry credentials and no docker config.json file provided: skipping secret creation")
if len(config.ContainerRegistryUser) == 0 && len(config.ContainerRegistryPassword) == 0 {
log.Entry().Info("No/incomplete container registry credentials provided: skipping secret creation")
if len(config.ContainerRegistrySecret) > 0 {
secretsData = fmt.Sprintf(",imagePullSecrets[0].name=%v", config.ContainerRegistrySecret)
}
} else {
var dockerRegistrySecret bytes.Buffer
utils.Stdout(&dockerRegistrySecret)
kubeSecretParams := defineKubeSecretParams(config, containerRegistry, utils)
err, kubeSecretParams := defineKubeSecretParams(config, containerRegistry, utils)
if err != nil {
log.Entry().WithError(err).Fatal("parameter definition for creating registry secret failed")
}
log.Entry().Infof("Calling kubectl create secret --dry-run=true ...")
log.Entry().Debugf("kubectl parameters %v", kubeSecretParams)
if err := utils.RunExecutable("kubectl", kubeSecretParams...); err != nil {
@@ -223,7 +228,7 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtils,
return nil
}
func runKubectlDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtils) error {
func runKubectlDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtils, stdout io.Writer) error {
_, containerRegistry, err := splitRegistryURL(config.ContainerRegistryURL)
if err != nil {
log.Entry().WithError(err).Fatalf("Container registry url '%v' incorrect", config.ContainerRegistryURL)
@@ -248,25 +253,41 @@ func runKubectlDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtil
kubeParams = append(kubeParams, fmt.Sprintf("--token=%v", config.KubeToken))
}
if config.CreateDockerRegistrySecret {
if len(config.DockerConfigJSON) == 0 && (len(config.ContainerRegistryUser) == 0 || len(config.ContainerRegistryPassword) == 0) {
log.Entry().Fatal("Cannot create Container registry secret without proper registry username/password or docker config.json file")
utils.Stdout(stdout)
if len(config.ContainerRegistryUser) == 0 && len(config.ContainerRegistryPassword) == 0 {
log.Entry().Info("No/incomplete container registry credentials provided: skipping secret creation")
} else {
err, kubeSecretParams := defineKubeSecretParams(config, containerRegistry, utils)
if err != nil {
log.Entry().WithError(err).Fatal("parameter definition for creating registry secret failed")
}
var dockerRegistrySecret bytes.Buffer
utils.Stdout(&dockerRegistrySecret)
log.Entry().Infof("Creating container registry secret '%v'", config.ContainerRegistrySecret)
kubeSecretParams = append(kubeSecretParams, kubeParams...)
log.Entry().Debugf("Running kubectl with following parameters: %v", kubeSecretParams)
if err := utils.RunExecutable("kubectl", kubeSecretParams...); err != nil {
log.Entry().WithError(err).Fatal("Creating container registry secret failed")
}
// first check if secret already exists
kubeCheckParams := append(kubeParams, "get", "secret", config.ContainerRegistrySecret)
var dockerRegistrySecretData map[string]interface{}
// ToDo: always update the secret using a yaml definition
if err := utils.RunExecutable("kubectl", kubeCheckParams...); err != nil {
log.Entry().Infof("Registry secret '%v' does not exist, let's create it ...", config.ContainerRegistrySecret)
kubeSecretParams := defineKubeSecretParams(config, containerRegistry, utils)
kubeSecretParams = append(kubeParams, kubeSecretParams...)
log.Entry().Infof("Creating container registry secret '%v'", config.ContainerRegistrySecret)
log.Entry().Debugf("Running kubectl with following parameters: %v", kubeSecretParams)
if err := utils.RunExecutable("kubectl", kubeSecretParams...); err != nil {
log.Entry().WithError(err).Fatal("Creating container registry secret failed")
}
if err := json.Unmarshal(dockerRegistrySecret.Bytes(), &dockerRegistrySecretData); err != nil {
log.Entry().WithError(err).Fatal("Reading docker registry secret json failed")
}
// write the json output to a file
tmpFolder := getTempDirForKubeCtlJson()
defer os.RemoveAll(tmpFolder) // clean up
jsonData, _ := json.Marshal(dockerRegistrySecretData)
ioutil.WriteFile(filepath.Join(tmpFolder, "secret.json"), jsonData, 0777)
kubeSecretApplyParams := []string{"apply", "-f", filepath.Join(tmpFolder, "secret.json")}
if err := utils.RunExecutable("kubectl", kubeSecretApplyParams...); err != nil {
log.Entry().WithError(err).Fatal("Creating container registry secret failed")
}
}
appTemplate, err := utils.FileRead(config.AppTemplate)
@@ -309,6 +330,14 @@ func runKubectlDeploy(config kubernetesDeployOptions, utils kubernetesDeployUtil
return nil
}
func getTempDirForKubeCtlJson() string {
tmpFolder, err := ioutil.TempDir(".", "temp-")
if err != nil {
log.Entry().WithError(err).WithField("path", tmpFolder).Debug("creating temp directory failed")
}
return tmpFolder
}
func splitRegistryURL(registryURL string) (protocol, registry string, err error) {
parts := strings.Split(registryURL, "://")
if len(parts) != 2 || len(parts[1]) == 0 {
@@ -333,44 +362,31 @@ func splitFullImageName(image string) (imageName, tag string, err error) {
return "", "", fmt.Errorf("Failed to split image name '%v'", image)
}
func defineKubeSecretParams(config kubernetesDeployOptions, containerRegistry string, utils kubernetesDeployUtils) []string {
kubeSecretParams := []string{
"create",
"secret",
}
if config.DeployTool == "helm" || config.DeployTool == "helm3" {
kubeSecretParams = append(
kubeSecretParams,
"--insecure-skip-tls-verify=true",
"--dry-run=true",
"--output=json",
)
}
func defineKubeSecretParams(config kubernetesDeployOptions, containerRegistry string, utils kubernetesDeployUtils) (error, []string) {
targetPath := ""
if len(config.DockerConfigJSON) > 0 {
// first enhance config.json with additional pipeline-related credentials if they have been provided
if len(containerRegistry) > 0 && len(config.ContainerRegistryUser) > 0 && len(config.ContainerRegistryPassword) > 0 {
var err error
_, err = piperDocker.CreateDockerConfigJSON(containerRegistry, config.ContainerRegistryUser, config.ContainerRegistryPassword, "", config.DockerConfigJSON, utils)
targetPath, err = docker.CreateDockerConfigJSON(containerRegistry, config.ContainerRegistryUser, config.ContainerRegistryPassword, "", config.DockerConfigJSON, utils)
if err != nil {
log.Entry().Warningf("failed to update Docker config.json: %v", err)
return err, []string{}
}
}
return append(
kubeSecretParams,
"generic",
config.ContainerRegistrySecret,
fmt.Sprintf("--from-file=.dockerconfigjson=%v", config.DockerConfigJSON),
"--type=kubernetes.io/dockerconfigjson",
)
} else {
return fmt.Errorf("no docker config json file found to update credentials '%v'", config.DockerConfigJSON), []string{}
}
return append(
kubeSecretParams,
"docker-registry",
return nil, []string{
"create",
"secret",
"generic",
config.ContainerRegistrySecret,
fmt.Sprintf("--docker-server=%v", containerRegistry),
fmt.Sprintf("--docker-username=%v", config.ContainerRegistryUser),
fmt.Sprintf("--docker-password=%v", config.ContainerRegistryPassword),
)
fmt.Sprintf("--from-file=.dockerconfigjson=%v", targetPath),
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json",
}
}

View File

@@ -75,7 +75,7 @@ helm upgrade <deploymentName> <chartPath> --install --force --namespace <namespa
* ` + "`" + `yourRegistry` + "`" + ` will be retrieved from ` + "`" + `containerRegistryUrl` + "`" + `
* ` + "`" + `yourImageName` + "`" + `, ` + "`" + `yourImageTag` + "`" + ` will be retrieved from ` + "`" + `image` + "`" + `
* ` + "`" + `dockerSecret` + "`" + ` will be calculated with a call to ` + "`" + `kubectl create secret docker-registry regsecret --docker-server=<yourRegistry> --docker-username=<containerRegistryUser> --docker-password=<containerRegistryPassword> --dry-run=true --output=json'` + "`" + ``,
* ` + "`" + `dockerSecret` + "`" + ` will be calculated with a call to ` + "`" + `kubectl create secret generic <containerRegistrySecret> --from-file=.dockerconfigjson=<dockerConfigJson> --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json` + "`" + ``,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
@@ -179,7 +179,7 @@ func addKubernetesDeployFlags(cmd *cobra.Command, stepConfig *kubernetesDeployOp
cmd.Flags().StringVar(&stepConfig.KubeToken, "kubeToken", os.Getenv("PIPER_kubeToken"), "Contains the id_token used by kubectl for authentication. Consider using kubeConfig parameter instead.")
cmd.Flags().StringVar(&stepConfig.Namespace, "namespace", `default`, "Defines the target Kubernetes namespace for the deployment.")
cmd.Flags().StringVar(&stepConfig.TillerNamespace, "tillerNamespace", os.Getenv("PIPER_tillerNamespace"), "Defines optional tiller namespace for deployments using helm.")
cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", os.Getenv("PIPER_dockerConfigJSON"), "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).")
cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", `.pipeline/docker/config.json`, "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).")
cmd.Flags().StringVar(&stepConfig.DeployCommand, "deployCommand", `apply`, "Only for `deployTool: kubectl`: defines the command `apply` or `replace`. The default is `apply`.")
cmd.MarkFlagRequired("containerRegistryUrl")
@@ -494,7 +494,7 @@ func kubernetesDeployMetadata() config.StepData {
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_dockerConfigJSON"),
Default: `.pipeline/docker/config.json`,
},
{
Name: "deployCommand",

View File

@@ -33,7 +33,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -45,13 +45,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DockerConfigJSON: ".pipeline/docker/config.json",
}
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: dockerConfigJSON,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: dockerConfigJSON,
}
var stdout bytes.Buffer
@@ -62,7 +63,9 @@ func TestRunKubernetesDeploy(t *testing.T) {
assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters")
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{"create", "secret", "generic", "testSecret", "--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson", "--insecure-skip-tls-verify=true", "--dry-run=client", "--output=json"},
mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command")
assert.Equal(t, []string{
@@ -90,7 +93,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -103,13 +106,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DockerConfigJSON: ".pipeline/docker/config.json",
}
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: dockerConfigJSON,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: dockerConfigJSON,
}
var stdout bytes.Buffer
@@ -120,7 +124,17 @@ func TestRunKubernetesDeploy(t *testing.T) {
assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters")
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{
"create",
"secret",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command")
@@ -129,27 +143,29 @@ func TestRunKubernetesDeploy(t *testing.T) {
t.Run("test helm - docker config.json path passed as parameter", func(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
DockerConfigJSON: "/path/to/.docker/config.json",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
DeployTool: "helm",
ForceUpdates: true,
HelmDeployWaitSeconds: 400,
IngressHosts: []string{"ingress.host1", "ingress.host2"},
Image: "path/to/Image:latest",
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
ContainerRegistryURL: "https://my.registry:55555",
DockerConfigJSON: "/path/to/.docker/config.json",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
DeployTool: "helm",
ForceUpdates: true,
HelmDeployWaitSeconds: 400,
IngressHosts: []string{"ingress.host1", "ingress.host2"},
Image: "path/to/Image:latest",
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
}
k8sSecretSpec := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile("/path/to/.docker/config.json", []byte("ThisIsOurBase64EncodedSecret=="))
mockUtils.AddFile("/path/to/.docker/config.json", []byte(`{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`))
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json generic testSecret --from-file=.dockerconfigjson=/path/to/.docker/config.json --type=kubernetes.io/dockerconfigjson`: k8sSecretSpec,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=/path/to/.docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: k8sSecretSpec,
}
var stdout bytes.Buffer
@@ -164,14 +180,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
assert.Equal(t, []string{
"create",
"secret",
"--insecure-skip-tls-verify=true",
"--dry-run=true",
"--output=json",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=/path/to/.docker/config.json",
`--type=kubernetes.io/dockerconfigjson`,
}, mockUtils.Calls[1].Params, "Wrong secret creation parameters")
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command")
assert.Equal(t, []string{
@@ -199,7 +215,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -212,13 +228,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
KeepFailedDeployments: true,
DockerConfigJSON: ".pipeline/docker/config.json",
}
k8sSecretSpec := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: k8sSecretSpec,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: k8sSecretSpec,
}
var stdout bytes.Buffer
@@ -229,7 +246,17 @@ func TestRunKubernetesDeploy(t *testing.T) {
assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters")
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{
"create",
"secret",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[1].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command")
assert.Equal(t, []string{
@@ -278,7 +305,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -290,13 +317,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DockerConfigJSON: ".pipeline/docker/config.json",
}
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: dockerConfigJSON,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: dockerConfigJSON,
}
var stdout bytes.Buffer
@@ -304,7 +332,17 @@ func TestRunKubernetesDeploy(t *testing.T) {
runKubernetesDeploy(opts, mockUtils, &stdout)
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{
"create",
"secret",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command")
assert.Equal(t, []string{
@@ -336,7 +374,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -349,13 +387,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
AdditionalParameters: []string{"--testParam", "testValue"},
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DockerConfigJSON: ".pipeline/docker/config.json",
}
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: dockerConfigJSON,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: dockerConfigJSON,
}
var stdout bytes.Buffer
@@ -363,7 +402,17 @@ func TestRunKubernetesDeploy(t *testing.T) {
runKubernetesDeploy(opts, mockUtils, &stdout)
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{
"create",
"secret",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command")
@@ -397,7 +446,7 @@ func TestRunKubernetesDeploy(t *testing.T) {
opts := kubernetesDeployOptions{
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "testSecret",
ChartPath: "path/to/chart",
DeploymentName: "deploymentName",
@@ -410,13 +459,14 @@ func TestRunKubernetesDeploy(t *testing.T) {
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
KeepFailedDeployments: true,
DockerConfigJSON: ".pipeline/docker/config.json",
}
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret --insecure-skip-tls-verify=true --dry-run=true --output=json docker-registry testSecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=\*\*\*\*\*\*\*\*`: dockerConfigJSON,
`kubectl create secret generic testSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json`: dockerConfigJSON,
}
var stdout bytes.Buffer
@@ -424,7 +474,17 @@ func TestRunKubernetesDeploy(t *testing.T) {
runKubernetesDeploy(opts, mockUtils, &stdout)
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command")
assert.Equal(t, []string{"create", "secret", "--insecure-skip-tls-verify=true", "--dry-run=true", "--output=json", "docker-registry", "testSecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********"}, mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, []string{
"create",
"secret",
"generic",
"testSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
"--dry-run=client",
"--output=json"},
mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command")
assert.Equal(t, []string{
@@ -578,89 +638,13 @@ func TestRunKubernetesDeploy(t *testing.T) {
}, mockUtils.Calls[0].Params, "Wrong upgrade parameters")
})
t.Run("test kubectl - create secret/kubeconfig", func(t *testing.T) {
opts := kubernetesDeployOptions{
AppTemplate: "path/to/test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
CreateDockerRegistrySecret: true,
DeployTool: "kubectl",
Image: "path/to/Image:latest",
AdditionalParameters: []string{"--testParam", "testValue"},
KubeConfig: "This is my kubeconfig",
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
}
kubeYaml := `kind: Deployment
metadata:
spec:
spec:
image: <image-name>`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile(opts.AppTemplate, []byte(kubeYaml))
mockUtils.ShouldFailOnCommand = map[string]error{
"kubectl --insecure-skip-tls-verify=true --namespace=deploymentNamespace --context=testCluster get secret regSecret": fmt.Errorf("secret not found"),
}
var stdout bytes.Buffer
runKubernetesDeploy(opts, mockUtils, &stdout)
assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"})
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret lookup command")
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
fmt.Sprintf("--context=%v", opts.KubeContext),
"get",
"secret",
opts.ContainerRegistrySecret,
}, mockUtils.Calls[0].Params, "kubectl parameters incorrect")
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret create command")
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
fmt.Sprintf("--context=%v", opts.KubeContext),
"create",
"secret",
"docker-registry",
opts.ContainerRegistrySecret,
"--docker-server=my.registry:55555",
fmt.Sprintf("--docker-username=%v", opts.ContainerRegistryUser),
fmt.Sprintf("--docker-password=%v", opts.ContainerRegistryPassword),
}, mockUtils.Calls[1].Params, "kubectl parameters incorrect")
assert.Equal(t, "kubectl", mockUtils.Calls[2].Exec, "Wrong apply command")
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
fmt.Sprintf("--context=%v", opts.KubeContext),
"apply",
"--filename",
opts.AppTemplate,
"--testParam",
"testValue",
}, mockUtils.Calls[2].Params, "kubectl parameters incorrect")
appTemplate, _ := mockUtils.FileRead(opts.AppTemplate)
assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest")
})
t.Run("test kubectl - create secret from docker config.json", func(t *testing.T) {
opts := kubernetesDeployOptions{
AppTemplate: "path/to/test.yaml",
DockerConfigJSON: "/path/to/.docker/config.json",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistryPassword: "dummy",
ContainerRegistrySecret: "regSecret",
CreateDockerRegistrySecret: true,
DeployTool: "kubectl",
@@ -670,18 +654,22 @@ spec:
KubeContext: "testCluster",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
DockerConfigJSON: ".pipeline/docker/config.json",
}
kubeYaml := `kind: Deployment
metadata:
spec:
spec:
image: <image-name>`
metadata:
spec:
spec:
image: <image-name>`
dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile(opts.AppTemplate, []byte(kubeYaml))
mockUtils.ShouldFailOnCommand = map[string]error{
"kubectl --insecure-skip-tls-verify=true --namespace=deploymentNamespace --context=testCluster get secret regSecret": fmt.Errorf("secret not found"),
mockUtils.StdoutReturn = map[string]string{
`kubectl create secret generic regSecret --from-file=.dockerconfigjson=.pipeline/docker/config.json --type=kubernetes.io/dockerconfigjson --insecure-skip-tls-verify=true --dry-run=client --output=json --insecure-skip-tls-verify=true --namespace=deploymentNamespace --context=testCluster`: dockerConfigJSON,
}
var stdout bytes.Buffer
runKubernetesDeploy(opts, mockUtils, &stdout)
@@ -689,73 +677,37 @@ spec:
assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"})
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
fmt.Sprintf("--context=%v", opts.KubeContext),
"create",
"secret",
"generic",
opts.ContainerRegistrySecret,
fmt.Sprintf("--from-file=.dockerconfigjson=%v", opts.DockerConfigJSON),
`--type=kubernetes.io/dockerconfigjson`,
}, mockUtils.Calls[1].Params, "kubectl parameters incorrect")
})
t.Run("test kubectl - lookup secret/kubeconfig", func(t *testing.T) {
opts := kubernetesDeployOptions{
AppTemplate: "path/to/test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
CreateDockerRegistrySecret: true,
DeployTool: "kubectl",
Image: "path/to/Image:latest",
KubeConfig: "This is my kubeconfig",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
}
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile(opts.AppTemplate, []byte("testYaml"))
var stdout bytes.Buffer
runKubernetesDeploy(opts, mockUtils, &stdout)
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret lookup command")
assert.Equal(t, []string{
"regSecret",
"--from-file=.dockerconfigjson=.pipeline/docker/config.json",
"--type=kubernetes.io/dockerconfigjson",
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
"get",
"secret",
opts.ContainerRegistrySecret,
}, mockUtils.Calls[0].Params, "kubectl parameters incorrect")
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong apply command")
assert.Equal(t, []string{
"--dry-run=client",
"--output=json",
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
"apply",
"--filename",
opts.AppTemplate,
}, mockUtils.Calls[1].Params, "kubectl parameters incorrect")
"--namespace=deploymentNamespace",
"--context=testCluster",
},
mockUtils.Calls[0].Params, "Wrong secret creation parameters")
assert.Containsf(t, mockUtils.Calls[1].Params, "apply", "Wrong secret creation parameters")
assert.Containsf(t, mockUtils.Calls[1].Params, "-f", "Wrong secret creation parameters")
})
t.Run("test kubectl - token only", func(t *testing.T) {
opts := kubernetesDeployOptions{
APIServer: "https://my.api.server",
AppTemplate: "path/to/test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
Image: "path/to/Image:latest",
KubeToken: "testToken",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
APIServer: "https://my.api.server",
AppTemplate: "path/to/test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
Image: "path/to/Image:latest",
KubeToken: "testToken",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
}
mockUtils := newKubernetesDeployMockUtils()
@@ -779,18 +731,16 @@ spec:
t.Run("test kubectl - with containerImageName and containerImageTag instead of image", func(t *testing.T) {
opts := kubernetesDeployOptions{
APIServer: "https://my.api.server",
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
ContainerImageTag: "latest",
ContainerImageName: "path/to/Image",
KubeConfig: "This is my kubeconfig",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
APIServer: "https://my.api.server",
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
ContainerImageTag: "latest",
ContainerImageName: "path/to/Image",
KubeConfig: "This is my kubeconfig",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
}
mockUtils := newKubernetesDeployMockUtils()
@@ -808,16 +758,14 @@ spec:
t.Run("test kubectl - fails without image information", func(t *testing.T) {
opts := kubernetesDeployOptions{
APIServer: "https://my.api.server",
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
KubeConfig: "This is my kubeconfig",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
APIServer: "https://my.api.server",
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistrySecret: "regSecret",
DeployTool: "kubectl",
KubeConfig: "This is my kubeconfig",
Namespace: "deploymentNamespace",
DeployCommand: "apply",
}
mockUtils := newKubernetesDeployMockUtils()
@@ -833,8 +781,6 @@ spec:
opts := kubernetesDeployOptions{
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
CreateDockerRegistrySecret: true,
DeployTool: "kubectl",
@@ -847,10 +793,10 @@ spec:
}
kubeYaml := `kind: Deployment
metadata:
spec:
spec:
image: <image-name>`
metadata:
spec:
spec:
image: <image-name>`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile("test.yaml", []byte(kubeYaml))
@@ -861,7 +807,7 @@ spec:
assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"})
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong replace command")
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong replace command")
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
@@ -871,7 +817,7 @@ spec:
opts.AppTemplate,
"--testParam",
"testValue",
}, mockUtils.Calls[1].Params, "kubectl parameters incorrect")
}, mockUtils.Calls[0].Params, "kubectl parameters incorrect")
appTemplate, err := mockUtils.FileRead(opts.AppTemplate)
assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest")
@@ -881,8 +827,6 @@ spec:
opts := kubernetesDeployOptions{
AppTemplate: "test.yaml",
ContainerRegistryURL: "https://my.registry:55555",
ContainerRegistryUser: "registryUser",
ContainerRegistryPassword: "********",
ContainerRegistrySecret: "regSecret",
CreateDockerRegistrySecret: true,
DeployTool: "kubectl",
@@ -896,10 +840,10 @@ spec:
}
kubeYaml := `kind: Deployment
metadata:
spec:
spec:
image: <image-name>`
metadata:
spec:
spec:
image: <image-name>`
mockUtils := newKubernetesDeployMockUtils()
mockUtils.AddFile("test.yaml", []byte(kubeYaml))
@@ -910,7 +854,7 @@ spec:
assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"})
assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong replace command")
assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong replace command")
assert.Equal(t, []string{
"--insecure-skip-tls-verify=true",
fmt.Sprintf("--namespace=%v", opts.Namespace),
@@ -921,7 +865,7 @@ spec:
"--force",
"--testParam",
"testValue",
}, mockUtils.Calls[1].Params, "kubectl parameters incorrect")
}, mockUtils.Calls[0].Params, "kubectl parameters incorrect")
appTemplate, err := mockUtils.FileRead(opts.AppTemplate)
assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest")