diff --git a/cmd/kubernetesDeploy.go b/cmd/kubernetesDeploy.go index 95e89d21bd..c0129a435b 100644 --- a/cmd/kubernetesDeploy.go +++ b/cmd/kubernetesDeploy.go @@ -51,21 +51,50 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUtils, if err != nil { log.Entry().WithError(err).Fatalf("Container registry url '%v' incorrect", config.ContainerRegistryURL) } - //support either image or containerImageName and containerImageTag - containerImageName := "" - containerImageTag := "" - if len(config.Image) > 0 { - containerImageName, containerImageTag, err = splitFullImageName(config.Image) - if err != nil { - log.Entry().WithError(err).Fatalf("Container image '%v' incorrect", config.Image) + helmValues := helmValues{} + + if len(config.ImageNames) > 0 { + if len(config.ImageNames) != len(config.ImageNameTags) { + log.SetErrorCategory(log.ErrorConfiguration) + return fmt.Errorf("number of imageNames and imageNameTags must be equal") + } + for i, key := range config.ImageNames { + name, tag, err := splitFullImageName(config.ImageNameTags[i]) + if err != nil { + log.Entry().WithError(err).Fatalf("Container image '%v' incorrect", config.ImageNameTags[i]) + } + + helmValues.add(joinKey("image", key, "repository"), fmt.Sprintf("%v/%v", containerRegistry, name)) + helmValues.add(joinKey("image", key, "tag"), tag) + + if len(config.ImageNames) == 1 { + helmValues.add("image.repository", fmt.Sprintf("%v/%v", containerRegistry, name)) + helmValues.add("image.tag", tag) + } } - } else if len(config.ContainerImageName) > 0 && len(config.ContainerImageTag) > 0 { - containerImageName = config.ContainerImageName - containerImageTag = config.ContainerImageTag } else { - return fmt.Errorf("image information not given - please either set image or containerImageName and containerImageTag") + //support either image or containerImageName and containerImageTag + containerImageName := "" + containerImageTag := "" + if len(config.Image) > 0 { + containerImageName, containerImageTag, err = splitFullImageName(config.Image) + if err != nil { + log.Entry().WithError(err).Fatalf("Container image '%v' incorrect", config.Image) + } + } else if len(config.ContainerImageName) > 0 && len(config.ContainerImageTag) > 0 { + containerImageName = config.ContainerImageName + containerImageTag = config.ContainerImageTag + } else { + return fmt.Errorf("image information not given - please either set image or containerImageName and containerImageTag") + } + helmValues.add("image.repository", fmt.Sprintf("%v/%v", containerRegistry, containerImageName)) + helmValues.add("image.tag", containerImageTag) + + helmValues.add(joinKey("image", containerImageName, "repository"), fmt.Sprintf("%v/%v", containerRegistry, containerImageName)) + helmValues.add(joinKey("image", containerImageName, "tag"), containerImageTag) } + helmLogFields := map[string]interface{}{} helmLogFields["Chart Path"] = config.ChartPath helmLogFields["Namespace"] = config.Namespace @@ -89,11 +118,10 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUtils, } } - var secretsData string 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) + helmValues.add("imagePullSecrets[0].name", config.ContainerRegistrySecret) } } else { var dockerRegistrySecret bytes.Buffer @@ -124,7 +152,9 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUtils, log.Entry().Debugf("Secret created: %v", string(dockerRegistrySecret.Bytes())) // 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) + helmValues.add("secret.name", config.ContainerRegistrySecret) + helmValues.add("secret.dockerconfigjson", dockerRegistrySecretData.Data.DockerConfJSON) + helmValues.add("imagePullSecrets[0].name", config.ContainerRegistrySecret) } // Deprecated functionality @@ -133,9 +163,8 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUtils, // Due to the way helm is implemented it is currently not possible to overwrite a part of a list: // see: https://github.com/helm/helm/issues/5711#issuecomment-636177594 // Recommended way is to use a custom values file which contains the appropriate data - ingressHosts := "" for i, h := range config.IngressHosts { - ingressHosts += fmt.Sprintf(",ingress.hosts[%v]=%v", i, h) + helmValues.add(fmt.Sprintf("ingress.hosts[%v]", i), h) } upgradeParams := []string{ @@ -152,8 +181,7 @@ func runHelmDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUtils, upgradeParams, "--install", "--namespace", config.Namespace, - "--set", - fmt.Sprintf("image.repository=%v/%v,image.tag=%v%v%v", containerRegistry, containerImageName, containerImageTag, secretsData, ingressHosts), + "--set", helmValues.marshal(), ) if config.ForceUpdates { @@ -311,6 +339,42 @@ func runKubectlDeploy(config kubernetesDeployOptions, utils kubernetes.DeployUti return nil } +type helmValues []struct { + key, value string +} + +func joinKey(parts ...string) string { + escapedParts := make([]string, 0, len(parts)) + replacer := strings.NewReplacer(".", "\\.", "=", "\\=") + for _, part := range parts { + escapedParts = append(escapedParts, replacer.Replace(part)) + } + return strings.Join(escapedParts, ".") +} + +func (values *helmValues) add(key, value string) { + *values = append(*values, struct { + key string + value string + }{ + key: key, + value: value, + }) +} + +func (values helmValues) marshal() string { + builder := strings.Builder{} + for idx, item := range values { + if idx > 0 { + builder.WriteString(",") + } + builder.WriteString(item.key) + builder.WriteString("=") + builder.WriteString(item.value) + } + return builder.String() +} + func getTempDirForKubeCtlJson() string { tmpFolder, err := ioutil.TempDir(".", "temp-") if err != nil { diff --git a/cmd/kubernetesDeploy_generated.go b/cmd/kubernetesDeploy_generated.go index 62519d0a7d..faaf8e6c6e 100644 --- a/cmd/kubernetesDeploy_generated.go +++ b/cmd/kubernetesDeploy_generated.go @@ -33,6 +33,8 @@ type kubernetesDeployOptions struct { HelmDeployWaitSeconds int `json:"helmDeployWaitSeconds,omitempty"` HelmValues []string `json:"helmValues,omitempty"` Image string `json:"image,omitempty"` + ImageNames []string `json:"imageNames,omitempty"` + ImageNameTags []string `json:"imageNameTags,omitempty"` IngressHosts []string `json:"ingressHosts,omitempty"` KeepFailedDeployments bool `json:"keepFailedDeployments,omitempty"` RunHelmTests bool `json:"runHelmTests,omitempty"` @@ -174,6 +176,8 @@ func addKubernetesDeployFlags(cmd *cobra.Command, stepConfig *kubernetesDeployOp cmd.Flags().IntVar(&stepConfig.HelmDeployWaitSeconds, "helmDeployWaitSeconds", 300, "Number of seconds before helm deploy returns.") cmd.Flags().StringSliceVar(&stepConfig.HelmValues, "helmValues", []string{}, "List of helm values as YAML file reference or URL (as per helm parameter description for `-f` / `--values`)") cmd.Flags().StringVar(&stepConfig.Image, "image", os.Getenv("PIPER_image"), "Full name of the image to be deployed.") + cmd.Flags().StringSliceVar(&stepConfig.ImageNames, "imageNames", []string{}, "List of names of the images to be deployed.") + cmd.Flags().StringSliceVar(&stepConfig.ImageNameTags, "imageNameTags", []string{}, "List of full names (registry and tag) of the images to be deployed.") cmd.Flags().StringSliceVar(&stepConfig.IngressHosts, "ingressHosts", []string{}, "(Deprecated) List of ingress hosts to be exposed via helm deployment.") cmd.Flags().BoolVar(&stepConfig.KeepFailedDeployments, "keepFailedDeployments", false, "Defines whether a failed deployment will be purged") cmd.Flags().BoolVar(&stepConfig.RunHelmTests, "runHelmTests", false, "Defines whether or not to run helm tests against the recently deployed release") @@ -401,6 +405,34 @@ func kubernetesDeployMetadata() config.StepData { Aliases: []config.Alias{{Name: "deployImage"}}, Default: os.Getenv("PIPER_image"), }, + { + Name: "imageNames", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "container/imageNames", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "[]string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: []string{}, + }, + { + Name: "imageNameTags", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "container/imageNameTags", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "[]string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: []string{}, + }, { Name: "ingressHosts", ResourceRef: []config.ResourceReference{}, diff --git a/cmd/kubernetesDeploy_test.go b/cmd/kubernetesDeploy_test.go index ee86e51c6c..fa34767670 100644 --- a/cmd/kubernetesDeploy_test.go +++ b/cmd/kubernetesDeploy_test.go @@ -9,6 +9,7 @@ import ( "github.com/SAP/jenkins-library/pkg/telemetry" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type kubernetesDeployMockUtils struct { @@ -79,7 +80,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "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", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", "--force", "--wait", "--timeout", @@ -146,7 +147,7 @@ func TestRunKubernetesDeploy(t *testing.T) { assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command") - assert.Contains(t, mockUtils.Calls[2].Params, "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", "Wrong upgrade parameters") + assert.Contains(t, mockUtils.Calls[2].Params, "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", "Wrong upgrade parameters") }) t.Run("test helm - docker config.json path passed as parameter", func(t *testing.T) { @@ -206,7 +207,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "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", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", "--force", "--wait", "--timeout", @@ -275,7 +276,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "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", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret,ingress.hosts[0]=ingress.host1,ingress.hosts[1]=ingress.host2", "--force", "--wait", "--timeout", @@ -366,7 +367,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -441,7 +442,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -520,7 +521,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -600,7 +601,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -661,10 +662,143 @@ func TestRunKubernetesDeploy(t *testing.T) { assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") - assert.Contains(t, mockUtils.Calls[1].Params, "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "Wrong upgrade parameters") + assert.Contains(t, mockUtils.Calls[1].Params, "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "Wrong upgrade parameters") }) + t.Run("test helm v3 - with multiple images", func(t *testing.T) { + opts := kubernetesDeployOptions{ + ContainerRegistryURL: "https://my.registry:55555", + ContainerRegistryUser: "registryUser", + ContainerRegistryPassword: "dummy", + ContainerRegistrySecret: "testSecret", + ChartPath: "path/to/chart", + DeploymentName: "deploymentName", + DeployTool: "helm3", + ForceUpdates: true, + HelmDeployWaitSeconds: 400, + HelmValues: []string{"values1.yaml", "values2.yaml"}, + ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, + ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, + 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 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 + + require.NoError(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout)) + + assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") + 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.Contains(t, mockUtils.Calls[1].Params, `image.myImage.repository=my.registry:55555/myImage,image.myImage.tag=myTag,image.myImage\.sub1.repository=my.registry:55555/myImage-sub1,image.myImage\.sub1.tag=myTag,image.myImage\.sub2.repository=my.registry:55555/myImage-sub2,image.myImage\.sub2.tag=myTag,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret`, "Wrong upgrade parameters") + + }) + + t.Run("test helm v3 - with one image in multiple images array", func(t *testing.T) { + opts := kubernetesDeployOptions{ + ContainerRegistryURL: "https://my.registry:55555", + ContainerRegistryUser: "registryUser", + ContainerRegistryPassword: "dummy", + ContainerRegistrySecret: "testSecret", + ChartPath: "path/to/chart", + DeploymentName: "deploymentName", + DeployTool: "helm3", + ForceUpdates: true, + HelmDeployWaitSeconds: 400, + HelmValues: []string{"values1.yaml", "values2.yaml"}, + ImageNames: []string{"myImage"}, + ImageNameTags: []string{"myImage:myTag"}, + 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 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 + + require.NoError(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout)) + + assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") + 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.Contains(t, mockUtils.Calls[1].Params, `image.myImage.repository=my.registry:55555/myImage,image.myImage.tag=myTag,image.repository=my.registry:55555/myImage,image.tag=myTag,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret`, "Wrong upgrade parameters") + + }) + + t.Run("test helm v3 - with multiple images - missing ImageNameTags", func(t *testing.T) { + opts := kubernetesDeployOptions{ + ContainerRegistryURL: "https://my.registry:55555", + ContainerRegistryUser: "registryUser", + ContainerRegistryPassword: "dummy", + ContainerRegistrySecret: "testSecret", + ChartPath: "path/to/chart", + DeploymentName: "deploymentName", + DeployTool: "helm3", + ForceUpdates: true, + HelmDeployWaitSeconds: 400, + HelmValues: []string{"values1.yaml", "values2.yaml"}, + ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, + ImageNameTags: []string{"myImage:myTag"}, + 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 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 + + err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) + assert.EqualError(t, err, "number of imageNames and imageNameTags must be equal") + }) + t.Run("test helm3 - fails without image information", func(t *testing.T) { opts := kubernetesDeployOptions{ ContainerRegistryURL: "https://my.registry:55555", @@ -744,7 +878,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -787,7 +921,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,imagePullSecrets[0].name=testSecret", "--force", "--wait", "--timeout", @@ -871,7 +1005,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "--namespace", "deploymentNamespace", "--set", - "image.repository=my.registry:55555/path/to/Image,image.tag=latest,imagePullSecrets[0].name=testSecret", + "image.repository=my.registry:55555/path/to/Image,image.tag=latest,image.path/to/Image.repository=my.registry:55555/path/to/Image,image.path/to/Image.tag=latest,imagePullSecrets[0].name=testSecret", "--wait", "--timeout", "400s", diff --git a/resources/metadata/kubernetesDeploy.yaml b/resources/metadata/kubernetesDeploy.yaml index c17302b23c..4434e4bd53 100644 --- a/resources/metadata/kubernetesDeploy.yaml +++ b/resources/metadata/kubernetesDeploy.yaml @@ -236,6 +236,26 @@ spec: - PARAMETERS - STAGES - STEPS + - name: imageNames + type: "[]string" + description: List of names of the images to be deployed. + resourceRef: + - name: commonPipelineEnvironment + param: container/imageNames + scope: + - PARAMETERS + - STAGES + - STEPS + - name: imageNameTags + type: "[]string" + description: List of full names (registry and tag) of the images to be deployed. + resourceRef: + - name: commonPipelineEnvironment + param: container/imageNameTags + scope: + - PARAMETERS + - STAGES + - STEPS - name: ingressHosts type: "[]string" description: (Deprecated) List of ingress hosts to be exposed via helm deployment.