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 
			
		
		
		
	Add helm dependency command (#3669)
* Add helm dependency command * Change name of flag for package command Co-authored-by: “Vitalii <“vitalii.sidorov@sap.com”> Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
		| @@ -17,7 +17,8 @@ func helmExecute(config helmExecuteOptions, telemetryData *telemetry.CustomData) | ||||
| 		KubeConfig:                config.KubeConfig, | ||||
| 		HelmDeployWaitSeconds:     config.HelmDeployWaitSeconds, | ||||
| 		AppVersion:                config.AppVersion, | ||||
| 		DependencyUpdate:          config.DependencyUpdate, | ||||
| 		Dependency:                config.Dependency, | ||||
| 		PackageDependencyUpdate:   config.PackageDependencyUpdate, | ||||
| 		HelmValues:                config.HelmValues, | ||||
| 		FilterTest:                config.FilterTest, | ||||
| 		DumpLogs:                  config.DumpLogs, | ||||
| @@ -69,9 +70,9 @@ func runHelmExecute(config helmExecuteOptions, helmExecutor kubernetes.HelmExecu | ||||
| 		if err := helmExecutor.RunHelmUninstall(); err != nil { | ||||
| 			return fmt.Errorf("failed to execute helm uninstall: %v", err) | ||||
| 		} | ||||
| 	case "package": | ||||
| 		if err := helmExecutor.RunHelmPackage(); err != nil { | ||||
| 			return fmt.Errorf("failed to execute helm package: %v", err) | ||||
| 	case "dependency": | ||||
| 		if err := helmExecutor.RunHelmDependency(); err != nil { | ||||
| 			return fmt.Errorf("failed to execute helm dependency: %v", err) | ||||
| 		} | ||||
| 	case "publish": | ||||
| 		if err := helmExecutor.RunHelmPublish(); err != nil { | ||||
| @@ -91,8 +92,10 @@ func runHelmExecuteDefault(config helmExecuteOptions, helmExecutor kubernetes.He | ||||
| 		return fmt.Errorf("failed to execute helm lint: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := helmExecutor.RunHelmPackage(); err != nil { | ||||
| 		return fmt.Errorf("failed to execute helm package: %v", err) | ||||
| 	if len(config.Dependency) > 0 { | ||||
| 		if err := helmExecutor.RunHelmDependency(); err != nil { | ||||
| 			return fmt.Errorf("failed to execute helm dependency: %v", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if config.Publish { | ||||
|   | ||||
| @@ -30,9 +30,10 @@ type helmExecuteOptions struct { | ||||
| 	KubeContext               string   `json:"kubeContext,omitempty"` | ||||
| 	Namespace                 string   `json:"namespace,omitempty"` | ||||
| 	DockerConfigJSON          string   `json:"dockerConfigJSON,omitempty"` | ||||
| 	HelmCommand               string   `json:"helmCommand,omitempty" validate:"possible-values=upgrade install lint test uninstall package publish"` | ||||
| 	HelmCommand               string   `json:"helmCommand,omitempty" validate:"possible-values=upgrade lint install test uninstall dependency publish"` | ||||
| 	AppVersion                string   `json:"appVersion,omitempty"` | ||||
| 	DependencyUpdate          bool     `json:"dependencyUpdate,omitempty"` | ||||
| 	Dependency                string   `json:"dependency,omitempty" validate:"possible-values=build list update"` | ||||
| 	PackageDependencyUpdate   bool     `json:"packageDependencyUpdate,omitempty"` | ||||
| 	DumpLogs                  bool     `json:"dumpLogs,omitempty"` | ||||
| 	FilterTest                string   `json:"filterTest,omitempty"` | ||||
| 	CustomTLSCertificateLinks []string `json:"customTlsCertificateLinks,omitempty"` | ||||
| @@ -62,15 +63,15 @@ Executes helm functionality as the package manager for Kubernetes. | ||||
| * [Helm Charts] (https://artifacthub.io/) | ||||
| ` + "`" + `` + "`" + `` + "`" + ` | ||||
| Available Commands: | ||||
|   install     install a chart | ||||
|   lint        examine a chart for possible issues | ||||
|   package     package a chart directory into a chart archive | ||||
|   repo        add, list, remove, update, and index chart repositories | ||||
|   test        run tests for a release | ||||
|   uninstall   uninstall a release | ||||
|   upgrade     upgrade a release | ||||
|   verify      verify that a chart at the given path has been signed and is valid | ||||
|   push        upload a chart to a registry | ||||
| ` + "`" + `upgrade` + "`" + `, ` + "`" + `lint` + "`" + `, ` + "`" + `install` + "`" + `, ` + "`" + `test` + "`" + `, ` + "`" + `uninstall` + "`" + `, ` + "`" + `dependency` + "`" + `, ` + "`" + `publish` + "`" + ` | ||||
|  | ||||
|   upgrade       upgrade a release | ||||
|   lint          examine a chart for possible issues | ||||
|   install       install a chart | ||||
|   test          run tests for a release | ||||
|   uninstall     uninstall a release | ||||
|   dependency     package a chart directory into a chart archive | ||||
|   publish       package and puslish a release | ||||
|  | ||||
| ` + "`" + `` + "`" + `` + "`" + ` | ||||
|  | ||||
| @@ -167,9 +168,10 @@ func addHelmExecuteFlags(cmd *cobra.Command, stepConfig *helmExecuteOptions) { | ||||
| 	cmd.Flags().StringVar(&stepConfig.KubeContext, "kubeContext", os.Getenv("PIPER_kubeContext"), "Defines the context to use from the \"kubeconfig\" file.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Namespace, "namespace", `default`, "Defines the target Kubernetes namespace for the deployment.") | ||||
| 	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.HelmCommand, "helmCommand", os.Getenv("PIPER_helmCommand"), "Helm: defines the command `install`, `lint`, `package`, `test`, `upgrade` and etc.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.HelmCommand, "helmCommand", os.Getenv("PIPER_helmCommand"), "Helm: defines the command `upgrade`, `lint`, `install`, `test`, `uninstall`, `dependency`, `publish`.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.AppVersion, "appVersion", os.Getenv("PIPER_appVersion"), "set the appVersion on the chart to this version") | ||||
| 	cmd.Flags().BoolVar(&stepConfig.DependencyUpdate, "dependencyUpdate", false, "set the appVersion on the chart to this version") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Dependency, "dependency", os.Getenv("PIPER_dependency"), "manage a chart's dependencies") | ||||
| 	cmd.Flags().BoolVar(&stepConfig.PackageDependencyUpdate, "packageDependencyUpdate", false, "update dependencies from \"Chart.yaml\" to dir \"charts/\" before packaging") | ||||
| 	cmd.Flags().BoolVar(&stepConfig.DumpLogs, "dumpLogs", false, "dump the logs from test pods (this runs after all tests are complete, but before any cleanup)") | ||||
| 	cmd.Flags().StringVar(&stepConfig.FilterTest, "filterTest", os.Getenv("PIPER_filterTest"), "specify tests by attribute (currently `name`) using attribute=value syntax or `!attribute=value` to exclude a test (can specify multiple or separate values with commas `name=test1,name=test2`)") | ||||
| 	cmd.Flags().StringSliceVar(&stepConfig.CustomTLSCertificateLinks, "customTlsCertificateLinks", []string{}, "List of download links to custom TLS certificates. This is required to ensure trusted connections to instances with repositories (like nexus) when publish flag is set to true.") | ||||
| @@ -399,7 +401,16 @@ func helmExecuteMetadata() config.StepData { | ||||
| 						Default:     os.Getenv("PIPER_appVersion"), | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "dependencyUpdate", | ||||
| 						Name:        "dependency", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   false, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 						Default:     os.Getenv("PIPER_dependency"), | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "packageDependencyUpdate", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "bool", | ||||
|   | ||||
| @@ -196,7 +196,7 @@ func TestRunHelmUninstall(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestRunHelmPackage(t *testing.T) { | ||||
| func TestRunHelmDependency(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	testTable := []struct { | ||||
| @@ -206,23 +206,23 @@ func TestRunHelmPackage(t *testing.T) { | ||||
| 	}{ | ||||
| 		{ | ||||
| 			config: helmExecuteOptions{ | ||||
| 				HelmCommand: "package", | ||||
| 				HelmCommand: "dependency", | ||||
| 			}, | ||||
| 			methodError: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			config: helmExecuteOptions{ | ||||
| 				HelmCommand: "package", | ||||
| 				HelmCommand: "dependency", | ||||
| 			}, | ||||
| 			methodError:    errors.New("some error"), | ||||
| 			expectedErrStr: "failed to execute helm package: some error", | ||||
| 			expectedErrStr: "failed to execute helm dependency: some error", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for i, testCase := range testTable { | ||||
| 		t.Run(fmt.Sprint("case ", i), func(t *testing.T) { | ||||
| 			helmExecute := &mocks.HelmExecutor{} | ||||
| 			helmExecute.On("RunHelmPackage").Return(testCase.methodError) | ||||
| 			helmExecute.On("RunHelmDependency").Return(testCase.methodError) | ||||
|  | ||||
| 			err := runHelmExecute(testCase.config, helmExecute) | ||||
| 			if err != nil { | ||||
| @@ -300,7 +300,7 @@ func TestRunHelmDefaultCommand(t *testing.T) { | ||||
| 				HelmCommand: "", | ||||
| 			}, | ||||
| 			methodPackageError: errors.New("some error"), | ||||
| 			expectedErrStr:     "failed to execute helm package: some error", | ||||
| 			expectedErrStr:     "failed to execute helm dependency: some error", | ||||
| 		}, | ||||
| 		{ | ||||
| 			config: helmExecuteOptions{ | ||||
| @@ -315,7 +315,7 @@ func TestRunHelmDefaultCommand(t *testing.T) { | ||||
| 		t.Run(fmt.Sprint("case ", i), func(t *testing.T) { | ||||
| 			helmExecute := &mocks.HelmExecutor{} | ||||
| 			helmExecute.On("RunHelmLint").Return(testCase.methodLintError) | ||||
| 			helmExecute.On("RunHelmPackage").Return(testCase.methodPackageError) | ||||
| 			helmExecute.On("RunHelmDependency").Return(testCase.methodPackageError) | ||||
| 			helmExecute.On("RunHelmPublish").Return(testCase.methodPublishError) | ||||
|  | ||||
| 			err := runHelmExecute(testCase.config, helmExecute) | ||||
|   | ||||
| @@ -16,9 +16,9 @@ type HelmExecutor interface { | ||||
| 	RunHelmLint() error | ||||
| 	RunHelmInstall() error | ||||
| 	RunHelmUninstall() error | ||||
| 	RunHelmPackage() error | ||||
| 	RunHelmTest() error | ||||
| 	RunHelmPublish() error | ||||
| 	RunHelmDependency() error | ||||
| } | ||||
|  | ||||
| // HelmExecute struct | ||||
| @@ -45,7 +45,8 @@ type HelmExecuteOptions struct { | ||||
| 	DockerConfigJSON          string   `json:"dockerConfigJSON,omitempty"` | ||||
| 	PackageVersion            string   `json:"packageVersion,omitempty"` | ||||
| 	AppVersion                string   `json:"appVersion,omitempty"` | ||||
| 	DependencyUpdate          bool     `json:"dependencyUpdate,omitempty"` | ||||
| 	Dependency                string   `json:"dependency,omitempty" validate:"possible-values=build list update"` | ||||
| 	PackageDependencyUpdate   bool     `json:"packageDependencyUpdate,omitempty"` | ||||
| 	DumpLogs                  bool     `json:"dumpLogs,omitempty"` | ||||
| 	FilterTest                string   `json:"filterTest,omitempty"` | ||||
| 	TargetRepositoryURL       string   `json:"targetRepositoryURL,omitempty"` | ||||
| @@ -265,7 +266,7 @@ func (h *HelmExecute) RunHelmUninstall() error { | ||||
| } | ||||
|  | ||||
| // RunHelmPackage is used to package a chart directory into a chart archive | ||||
| func (h *HelmExecute) RunHelmPackage() error { | ||||
| func (h *HelmExecute) runHelmPackage() error { | ||||
| 	err := h.runHelmInit() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to execute deployments: %v", err) | ||||
| @@ -278,7 +279,7 @@ func (h *HelmExecute) RunHelmPackage() error { | ||||
| 	if len(h.config.PackageVersion) > 0 { | ||||
| 		helmParams = append(helmParams, "--version", h.config.PackageVersion) | ||||
| 	} | ||||
| 	if h.config.DependencyUpdate { | ||||
| 	if h.config.PackageDependencyUpdate { | ||||
| 		helmParams = append(helmParams, "--dependency-update") | ||||
| 	} | ||||
| 	if len(h.config.AppVersion) > 0 { | ||||
| @@ -323,6 +324,31 @@ func (h *HelmExecute) RunHelmTest() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // RunHelmDependency is used to manage a chart's dependencies | ||||
| func (h *HelmExecute) RunHelmDependency() error { | ||||
| 	if len(h.config.Dependency) == 0 { | ||||
| 		return fmt.Errorf("there is no dependency value. Possible values are build, list, update") | ||||
| 	} | ||||
|  | ||||
| 	helmParams := []string{ | ||||
| 		"dependency", | ||||
| 	} | ||||
|  | ||||
| 	helmParams = append(helmParams, h.config.Dependency) | ||||
|  | ||||
| 	helmParams = append(helmParams, h.config.ChartPath) | ||||
|  | ||||
| 	if len(h.config.AdditionalParameters) > 0 { | ||||
| 		helmParams = append(helmParams, h.config.AdditionalParameters...) | ||||
| 	} | ||||
|  | ||||
| 	if err := h.runHelmCommand(helmParams); err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Helm dependency call failed") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| //RunHelmPublish is used to upload a chart to a registry | ||||
| func (h *HelmExecute) RunHelmPublish() error { | ||||
| 	err := h.runHelmInit() | ||||
| @@ -330,6 +356,11 @@ func (h *HelmExecute) RunHelmPublish() error { | ||||
| 		return fmt.Errorf("failed to execute deployments: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err = h.runHelmPackage() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to execute deployments: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if len(h.config.TargetRepositoryURL) == 0 { | ||||
| 		return fmt.Errorf("there's no target repository for helm chart publishing configured") | ||||
| 	} | ||||
|   | ||||
| @@ -241,11 +241,11 @@ func TestRunHelm(t *testing.T) { | ||||
| 			}, | ||||
| 			{ | ||||
| 				config: HelmExecuteOptions{ | ||||
| 					ChartPath:        ".", | ||||
| 					DeploymentName:   "testPackage", | ||||
| 					PackageVersion:   "1.2.3", | ||||
| 					DependencyUpdate: true, | ||||
| 					AppVersion:       "9.8.7", | ||||
| 					ChartPath:               ".", | ||||
| 					DeploymentName:          "testPackage", | ||||
| 					PackageVersion:          "1.2.3", | ||||
| 					PackageDependencyUpdate: true, | ||||
| 					AppVersion:              "9.8.7", | ||||
| 				}, | ||||
| 				expectedConfig: []string{"package", ".", "--version", "1.2.3", "--dependency-update", "--app-version", "9.8.7"}, | ||||
| 			}, | ||||
| @@ -258,7 +258,7 @@ func TestRunHelm(t *testing.T) { | ||||
| 				verbose: false, | ||||
| 				stdout:  log.Writer(), | ||||
| 			} | ||||
| 			err := helmExecute.RunHelmPackage() | ||||
| 			err := helmExecute.runHelmPackage() | ||||
| 			assert.NoError(t, err) | ||||
| 			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[i]) | ||||
| 		} | ||||
| @@ -373,6 +373,50 @@ func TestRunHelm(t *testing.T) { | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Helm dependency command", func(t *testing.T) { | ||||
| 		utils := newHelmMockUtilsBundle() | ||||
|  | ||||
| 		testTable := []struct { | ||||
| 			config         HelmExecuteOptions | ||||
| 			expectedError  error | ||||
| 			expectedResult []string | ||||
| 		}{ | ||||
| 			{ | ||||
| 				config: HelmExecuteOptions{ | ||||
| 					ChartPath: ".", | ||||
| 				}, | ||||
| 				expectedError:  errors.New("there is no dependency value. Possible values are build, list, update"), | ||||
| 				expectedResult: nil, | ||||
| 			}, | ||||
| 			{ | ||||
| 				config: HelmExecuteOptions{ | ||||
| 					ChartPath:  ".", | ||||
| 					Dependency: "update", | ||||
| 				}, | ||||
| 				expectedError:  nil, | ||||
| 				expectedResult: []string{"dependency", "update", "."}, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| 		for _, testCase := range testTable { | ||||
| 			helmExecute := HelmExecute{ | ||||
| 				utils:   utils, | ||||
| 				config:  testCase.config, | ||||
| 				verbose: false, | ||||
| 				stdout:  log.Writer(), | ||||
| 			} | ||||
| 			err := helmExecute.RunHelmDependency() | ||||
| 			if testCase.expectedError != nil { | ||||
| 				assert.Error(t, err) | ||||
| 				assert.Equal(t, testCase.expectedError, err) | ||||
| 			} else { | ||||
| 				assert.NoError(t, err) | ||||
| 				assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedResult}, utils.Calls[0]) | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Helm publish command", func(t *testing.T) { | ||||
| 		utils := newHelmMockUtilsBundle() | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,8 @@ type HelmExecutor struct { | ||||
| 	mock.Mock | ||||
| } | ||||
|  | ||||
| // RunHelmAdd provides a mock function with given fields: | ||||
| func (_m *HelmExecutor) RunHelmAdd() error { | ||||
| // RunHelmDependency provides a mock function with given fields: | ||||
| func (_m *HelmExecutor) RunHelmDependency() error { | ||||
| 	ret := _m.Called() | ||||
|  | ||||
| 	var r0 error | ||||
| @@ -51,20 +51,6 @@ func (_m *HelmExecutor) RunHelmLint() error { | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // RunHelmPackage provides a mock function with given fields: | ||||
| func (_m *HelmExecutor) RunHelmPackage() error { | ||||
| 	ret := _m.Called() | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func() error); ok { | ||||
| 		r0 = rf() | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // RunHelmPublish provides a mock function with given fields: | ||||
| func (_m *HelmExecutor) RunHelmPublish() error { | ||||
| 	ret := _m.Called() | ||||
|   | ||||
| @@ -11,15 +11,15 @@ metadata: | ||||
|     * [Helm Charts] (https://artifacthub.io/) | ||||
|     ``` | ||||
|     Available Commands: | ||||
|       install     install a chart | ||||
|       lint        examine a chart for possible issues | ||||
|       package     package a chart directory into a chart archive | ||||
|       repo        add, list, remove, update, and index chart repositories | ||||
|       test        run tests for a release | ||||
|       uninstall   uninstall a release | ||||
|       upgrade     upgrade a release | ||||
|       verify      verify that a chart at the given path has been signed and is valid | ||||
|       push        upload a chart to a registry | ||||
|     `upgrade`, `lint`, `install`, `test`, `uninstall`, `dependency`, `publish` | ||||
|  | ||||
|       upgrade       upgrade a release | ||||
|       lint          examine a chart for possible issues | ||||
|       install       install a chart | ||||
|       test          run tests for a release | ||||
|       uninstall     uninstall a release | ||||
|       dependency     package a chart directory into a chart archive | ||||
|       publish       package and puslish a release | ||||
|  | ||||
|     ``` | ||||
|  | ||||
| @@ -189,18 +189,18 @@ spec: | ||||
|             default: docker-config | ||||
|       - name: helmCommand | ||||
|         type: string | ||||
|         description: "Helm: defines the command `install`, `lint`, `package`, `test`, `upgrade` and etc." | ||||
|         description: "Helm: defines the command `upgrade`, `lint`, `install`, `test`, `uninstall`, `dependency`, `publish`." | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         possibleValues: | ||||
|           - upgrade | ||||
|           - install | ||||
|           - lint | ||||
|           - install | ||||
|           - test | ||||
|           - uninstall | ||||
|           - package | ||||
|           - dependency | ||||
|           - publish | ||||
|       - name: appVersion | ||||
|         type: string | ||||
| @@ -210,9 +210,20 @@ spec: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|       - name: dependencyUpdate | ||||
|       - name: dependency | ||||
|         type: string | ||||
|         description: "manage a chart's dependencies" | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         possibleValues: | ||||
|           - build | ||||
|           - list | ||||
|           - update | ||||
|       - name: packageDependencyUpdate | ||||
|         type: bool | ||||
|         description: set the appVersion on the chart to this version | ||||
|         description: update dependencies from "Chart.yaml" to dir "charts/" before packaging | ||||
|         default: false | ||||
|         scope: | ||||
|           - GENERAL | ||||
|   | ||||
		Reference in New Issue
	
	Block a user