diff --git a/cmd/kubernetesDeploy.go b/cmd/kubernetesDeploy.go index 641bac18e..32ffcbee7 100644 --- a/cmd/kubernetesDeploy.go +++ b/cmd/kubernetesDeploy.go @@ -36,18 +36,30 @@ func kubernetesDeploy(config kubernetesDeployOptions, telemetryData *telemetry.C } // reroute stderr output to logging framework, stdout will be used for command interactions c.Stderr(log.Writer()) - runKubernetesDeploy(config, &c, log.Writer()) -} -func runKubernetesDeploy(config kubernetesDeployOptions, command command.ExecRunner, stdout io.Writer) { - if config.DeployTool == "helm" || config.DeployTool == "helm3" { - runHelmDeploy(config, command, stdout) - } else { - runKubectlDeploy(config, command) + // error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end + err := runKubernetesDeploy(config, &c, log.Writer()) + if err != nil { + log.Entry().WithError(err).Fatal("step execution failed") } } -func runHelmDeploy(config kubernetesDeployOptions, command command.ExecRunner, stdout io.Writer) { +func runKubernetesDeploy(config kubernetesDeployOptions, command command.ExecRunner, stdout io.Writer) error { + if config.DeployTool == "helm" || config.DeployTool == "helm3" { + return runHelmDeploy(config, command, stdout) + } else if config.DeployTool == "kubectl" { + return runKubectlDeploy(config, command) + } + return fmt.Errorf("Failed to execute deployments") +} + +func runHelmDeploy(config kubernetesDeployOptions, command command.ExecRunner, stdout io.Writer) error { + if len(config.ChartPath) <= 0 { + return fmt.Errorf("chart path has not been set, please configure chartPath parameter") + } + if len(config.DeploymentName) <= 0 { + return fmt.Errorf("deployment name has not been set, please configure deploymentName parameter") + } _, containerRegistry, err := splitRegistryURL(config.ContainerRegistryURL) if err != nil { log.Entry().WithError(err).Fatalf("Container registry url '%v' incorrect", config.ContainerRegistryURL) @@ -184,10 +196,10 @@ func runHelmDeploy(config kubernetesDeployOptions, command command.ExecRunner, s if err := command.RunExecutable("helm", upgradeParams...); err != nil { log.Entry().WithError(err).Fatal("Helm upgrade call failed") } - + return nil } -func runKubectlDeploy(config kubernetesDeployOptions, command command.ExecRunner) { +func runKubectlDeploy(config kubernetesDeployOptions, command command.ExecRunner) error { _, containerRegistry, err := splitRegistryURL(config.ContainerRegistryURL) if err != nil { log.Entry().WithError(err).Fatalf("Container registry url '%v' incorrect", config.ContainerRegistryURL) @@ -261,6 +273,7 @@ func runKubectlDeploy(config kubernetesDeployOptions, command command.ExecRunner log.Entry().Debugf("Running kubectl with following parameters: %v", kubeApplyParams) log.Entry().WithError(err).Fatal("Deployment with kubectl failed.") } + return nil } func splitRegistryURL(registryURL string) (protocol, registry string, err error) { diff --git a/cmd/kubernetesDeploy_generated.go b/cmd/kubernetesDeploy_generated.go index e6e7fb54c..6b692e75a 100644 --- a/cmd/kubernetesDeploy_generated.go +++ b/cmd/kubernetesDeploy_generated.go @@ -119,13 +119,13 @@ func addKubernetesDeployFlags(cmd *cobra.Command, stepConfig *kubernetesDeployOp cmd.Flags().StringSliceVar(&stepConfig.AdditionalParameters, "additionalParameters", []string{}, "Defines additional parameters for \"helm install\" or \"kubectl apply\" command.") cmd.Flags().StringVar(&stepConfig.APIServer, "apiServer", os.Getenv("PIPER_apiServer"), "Defines the Url of the API Server of the Kubernetes cluster.") cmd.Flags().StringVar(&stepConfig.AppTemplate, "appTemplate", os.Getenv("PIPER_appTemplate"), "Defines the filename for the kubernetes app template (e.g. k8s_apptemplate.yaml)") - cmd.Flags().StringVar(&stepConfig.ChartPath, "chartPath", os.Getenv("PIPER_chartPath"), "Defines the chart path for deployments using helm.") + cmd.Flags().StringVar(&stepConfig.ChartPath, "chartPath", os.Getenv("PIPER_chartPath"), "Defines the chart path for deployments using helm. It is a mandatory parameter when `deployTool:helm` or `deployTool:helm3`.") cmd.Flags().StringVar(&stepConfig.ContainerRegistryPassword, "containerRegistryPassword", os.Getenv("PIPER_containerRegistryPassword"), "Password for container registry access - typically provided by the CI/CD environment.") cmd.Flags().StringVar(&stepConfig.ContainerRegistryURL, "containerRegistryUrl", os.Getenv("PIPER_containerRegistryUrl"), "http(s) url of the Container registry where the image to deploy is located.") cmd.Flags().StringVar(&stepConfig.ContainerRegistryUser, "containerRegistryUser", os.Getenv("PIPER_containerRegistryUser"), "Username for container registry access - typically provided by the CI/CD environment.") cmd.Flags().StringVar(&stepConfig.ContainerRegistrySecret, "containerRegistrySecret", `regsecret`, "Name of the container registry secret used for pulling containers from the registry.") cmd.Flags().BoolVar(&stepConfig.CreateDockerRegistrySecret, "createDockerRegistrySecret", false, "Only for `deployTool:kubectl`: Toggle to turn on `containerRegistrySecret` creation.") - cmd.Flags().StringVar(&stepConfig.DeploymentName, "deploymentName", os.Getenv("PIPER_deploymentName"), "Defines the name of the deployment.") + cmd.Flags().StringVar(&stepConfig.DeploymentName, "deploymentName", os.Getenv("PIPER_deploymentName"), "Defines the name of the deployment. It is a mandatory parameter when `deployTool:helm` or `deployTool:helm3`.") cmd.Flags().StringVar(&stepConfig.DeployTool, "deployTool", `kubectl`, "Defines the tool which should be used for deployment.") cmd.Flags().BoolVar(&stepConfig.ForceUpdates, "forceUpdates", true, "Helm only: force resource updates with helm parameter `--force`") cmd.Flags().IntVar(&stepConfig.HelmDeployWaitSeconds, "helmDeployWaitSeconds", 300, "Number of seconds before helm deploy returns.") @@ -139,9 +139,7 @@ func addKubernetesDeployFlags(cmd *cobra.Command, stepConfig *kubernetesDeployOp 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.MarkFlagRequired("chartPath") cmd.MarkFlagRequired("containerRegistryUrl") - cmd.MarkFlagRequired("deploymentName") cmd.MarkFlagRequired("deployTool") cmd.MarkFlagRequired("image") } @@ -189,7 +187,7 @@ func kubernetesDeployMetadata() config.StepData { ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", - Mandatory: true, + Mandatory: false, Aliases: []config.Alias{{Name: "helmChartPath"}}, }, { @@ -254,7 +252,7 @@ func kubernetesDeployMetadata() config.StepData { ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", - Mandatory: true, + Mandatory: false, Aliases: []config.Alias{{Name: "helmDeploymentName"}}, }, { diff --git a/cmd/kubernetesDeploy_test.go b/cmd/kubernetesDeploy_test.go index 5f257344e..a8bf40062 100644 --- a/cmd/kubernetesDeploy_test.go +++ b/cmd/kubernetesDeploy_test.go @@ -293,6 +293,50 @@ func TestRunKubernetesDeploy(t *testing.T) { }, e.Calls[0].Params, "Wrong upgrade parameters") }) + t.Run("test helm v3 - fails without chart path", func(t *testing.T) { + opts := kubernetesDeployOptions{ + ContainerRegistryURL: "https://my.registry:55555", + ContainerRegistrySecret: "testSecret", + DeploymentName: "deploymentName", + DeployTool: "helm3", + ForceUpdates: true, + HelmDeployWaitSeconds: 400, + IngressHosts: []string{}, + Image: "path/to/Image:latest", + AdditionalParameters: []string{"--testParam", "testValue"}, + KubeContext: "testCluster", + Namespace: "deploymentNamespace", + } + e := mock.ExecMockRunner{} + + var stdout bytes.Buffer + + err := runKubernetesDeploy(opts, &e, &stdout) + assert.EqualError(t, err, "chart path has not been set, please configure chartPath parameter") + }) + + t.Run("test helm v3 - fails without deployment name", func(t *testing.T) { + opts := kubernetesDeployOptions{ + ContainerRegistryURL: "https://my.registry:55555", + ContainerRegistrySecret: "testSecret", + ChartPath: "path/to/chart", + DeployTool: "helm3", + ForceUpdates: true, + HelmDeployWaitSeconds: 400, + IngressHosts: []string{}, + Image: "path/to/Image:latest", + AdditionalParameters: []string{"--testParam", "testValue"}, + KubeContext: "testCluster", + Namespace: "deploymentNamespace", + } + e := mock.ExecMockRunner{} + + var stdout bytes.Buffer + + err := runKubernetesDeploy(opts, &e, &stdout) + assert.EqualError(t, err, "deployment name has not been set, please configure deploymentName parameter") + }) + t.Run("test helm v3 - no force", func(t *testing.T) { opts := kubernetesDeployOptions{ ContainerRegistryURL: "https://my.registry:55555", diff --git a/resources/metadata/kubernetesdeploy.yaml b/resources/metadata/kubernetesdeploy.yaml index 8b12e410c..1a8e88bcb 100644 --- a/resources/metadata/kubernetesdeploy.yaml +++ b/resources/metadata/kubernetesdeploy.yaml @@ -76,8 +76,7 @@ spec: aliases: - name: helmChartPath type: string - description: Defines the chart path for deployments using helm. - mandatory: true + description: Defines the chart path for deployments using helm. It is a mandatory parameter when `deployTool:helm` or `deployTool:helm3`. scope: - PARAMETERS - STAGES @@ -151,8 +150,7 @@ spec: aliases: - name: helmDeploymentName type: string - description: Defines the name of the deployment. - mandatory: true + description: Defines the name of the deployment. It is a mandatory parameter when `deployTool:helm` or `deployTool:helm3`. scope: - PARAMETERS - STAGES