github.com/jaylevin/jenkins-library@v1.230.4/pkg/kubernetes/helm_test.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/SAP/jenkins-library/pkg/log"
     8  	"github.com/SAP/jenkins-library/pkg/mock"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  type helmMockUtilsBundle struct {
    13  	*mock.ExecMockRunner
    14  	*mock.FilesMock
    15  	*mock.HttpClientMock
    16  }
    17  
    18  func newHelmMockUtilsBundle() helmMockUtilsBundle {
    19  	utils := helmMockUtilsBundle{
    20  		ExecMockRunner: &mock.ExecMockRunner{},
    21  		FilesMock:      &mock.FilesMock{},
    22  		HttpClientMock: &mock.HttpClientMock{
    23  			FileUploads: map[string]string{},
    24  		},
    25  	}
    26  	return utils
    27  }
    28  
    29  func TestRunHelm(t *testing.T) {
    30  
    31  	t.Run("Helm add command", func(t *testing.T) {
    32  		utils := newHelmMockUtilsBundle()
    33  
    34  		testTable := []struct {
    35  			config         HelmExecuteOptions
    36  			expectedConfig []string
    37  			generalVerbose bool
    38  		}{
    39  			{
    40  				config: HelmExecuteOptions{
    41  					TargetRepositoryURL:      "https://charts.helm.sh/stable",
    42  					TargetRepositoryName:     "stable",
    43  					TargetRepositoryUser:     "userAccount",
    44  					TargetRepositoryPassword: "pwdAccount",
    45  				},
    46  				expectedConfig: []string{"repo", "add", "--username", "userAccount", "--password", "pwdAccount", "stable", "https://charts.helm.sh/stable"},
    47  				generalVerbose: false,
    48  			},
    49  			{
    50  				config: HelmExecuteOptions{
    51  					TargetRepositoryURL:  "https://charts.helm.sh/stable",
    52  					TargetRepositoryName: "test",
    53  				},
    54  				expectedConfig: []string{"repo", "add", "test", "https://charts.helm.sh/stable", "--debug"},
    55  				generalVerbose: true,
    56  			},
    57  		}
    58  
    59  		for i, testCase := range testTable {
    60  			helmExecute := HelmExecute{
    61  				utils:   utils,
    62  				config:  testCase.config,
    63  				verbose: testCase.generalVerbose,
    64  				stdout:  log.Writer(),
    65  			}
    66  			err := helmExecute.runHelmAdd()
    67  			assert.NoError(t, err)
    68  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[i])
    69  		}
    70  	})
    71  
    72  	t.Run("Helm upgrade command", func(t *testing.T) {
    73  		utils := newHelmMockUtilsBundle()
    74  
    75  		testTable := []struct {
    76  			config                HelmExecuteOptions
    77  			generalVerbose        bool
    78  			expectedAddConfig     []string
    79  			expectedUpgradeConfig []string
    80  		}{
    81  			{
    82  				config: HelmExecuteOptions{
    83  					DeploymentName:        "test_deployment",
    84  					ChartPath:             ".",
    85  					Namespace:             "test_namespace",
    86  					ForceUpdates:          true,
    87  					HelmDeployWaitSeconds: 3456,
    88  					AdditionalParameters:  []string{"additional parameter"},
    89  					Image:                 "dtzar/helm-kubectl:3.4.1",
    90  					TargetRepositoryName:  "test",
    91  					TargetRepositoryURL:   "https://charts.helm.sh/stable",
    92  				},
    93  				generalVerbose:        true,
    94  				expectedAddConfig:     []string{"repo", "add", "test", "https://charts.helm.sh/stable", "--debug"},
    95  				expectedUpgradeConfig: []string{"upgrade", "test_deployment", ".", "--debug", "--install", "--namespace", "test_namespace", "--force", "--wait", "--timeout", "3456s", "--atomic", "additional parameter"},
    96  			},
    97  		}
    98  
    99  		for _, testCase := range testTable {
   100  			helmExecute := HelmExecute{
   101  				utils:   utils,
   102  				config:  testCase.config,
   103  				verbose: testCase.generalVerbose,
   104  				stdout:  log.Writer(),
   105  			}
   106  			err := helmExecute.RunHelmUpgrade()
   107  			assert.NoError(t, err)
   108  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedAddConfig}, utils.Calls[0])
   109  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedUpgradeConfig}, utils.Calls[1])
   110  		}
   111  	})
   112  
   113  	t.Run("Helm lint command", func(t *testing.T) {
   114  		utils := newHelmMockUtilsBundle()
   115  
   116  		testTable := []struct {
   117  			config         HelmExecuteOptions
   118  			expectedConfig []string
   119  		}{
   120  			{
   121  				config: HelmExecuteOptions{
   122  					ChartPath: ".",
   123  				},
   124  				expectedConfig: []string{"lint", "."},
   125  			},
   126  		}
   127  
   128  		for i, testCase := range testTable {
   129  			helmExecute := HelmExecute{
   130  				utils:   utils,
   131  				config:  testCase.config,
   132  				verbose: false,
   133  				stdout:  log.Writer(),
   134  			}
   135  			err := helmExecute.RunHelmLint()
   136  			assert.NoError(t, err)
   137  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[i])
   138  		}
   139  	})
   140  
   141  	t.Run("Helm install command", func(t *testing.T) {
   142  		t.Parallel()
   143  
   144  		testTable := []struct {
   145  			config                HelmExecuteOptions
   146  			generalVerbose        bool
   147  			expectedConfigInstall []string
   148  			expectedConfigAdd     []string
   149  		}{
   150  			{
   151  				config: HelmExecuteOptions{
   152  					ChartPath:             ".",
   153  					DeploymentName:        "testPackage",
   154  					Namespace:             "test-namespace",
   155  					HelmDeployWaitSeconds: 525,
   156  					TargetRepositoryURL:   "https://charts.helm.sh/stable",
   157  					TargetRepositoryName:  "test",
   158  				},
   159  				generalVerbose:        false,
   160  				expectedConfigAdd:     []string{"repo", "add", "test", "https://charts.helm.sh/stable"},
   161  				expectedConfigInstall: []string{"install", "testPackage", ".", "--namespace", "test-namespace", "--create-namespace", "--atomic", "--wait", "--timeout", "525s"},
   162  			},
   163  			{
   164  				config: HelmExecuteOptions{
   165  					ChartPath:             ".",
   166  					DeploymentName:        "testPackage",
   167  					Namespace:             "test-namespace",
   168  					HelmDeployWaitSeconds: 525,
   169  					KeepFailedDeployments: false,
   170  					AdditionalParameters:  []string{"--set-file my_script=dothings.sh"},
   171  					TargetRepositoryURL:   "https://charts.helm.sh/stable",
   172  					TargetRepositoryName:  "test",
   173  				},
   174  				generalVerbose:        true,
   175  				expectedConfigAdd:     []string{"repo", "add", "test", "https://charts.helm.sh/stable", "--debug"},
   176  				expectedConfigInstall: []string{"install", "testPackage", ".", "--namespace", "test-namespace", "--create-namespace", "--atomic", "--wait", "--timeout", "525s", "--set-file my_script=dothings.sh", "--debug", "--dry-run"},
   177  			},
   178  		}
   179  
   180  		for _, testCase := range testTable {
   181  			utils := newHelmMockUtilsBundle()
   182  			helmExecute := HelmExecute{
   183  				utils:   utils,
   184  				config:  testCase.config,
   185  				verbose: testCase.generalVerbose,
   186  				stdout:  log.Writer(),
   187  			}
   188  			err := helmExecute.RunHelmInstall()
   189  			assert.NoError(t, err)
   190  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfigAdd}, utils.Calls[0])
   191  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfigInstall}, utils.Calls[1])
   192  		}
   193  	})
   194  
   195  	t.Run("Helm uninstal command", func(t *testing.T) {
   196  		t.Parallel()
   197  
   198  		testTable := []struct {
   199  			config         HelmExecuteOptions
   200  			generalVerbose bool
   201  			expectedConfig []string
   202  		}{
   203  			{
   204  				config: HelmExecuteOptions{
   205  					ChartPath:            ".",
   206  					DeploymentName:       "testPackage",
   207  					Namespace:            "test-namespace",
   208  					TargetRepositoryName: "test",
   209  				},
   210  				expectedConfig: []string{"uninstall", "testPackage", "--namespace", "test-namespace"},
   211  			},
   212  			{
   213  				config: HelmExecuteOptions{
   214  					ChartPath:             ".",
   215  					DeploymentName:        "testPackage",
   216  					Namespace:             "test-namespace",
   217  					HelmDeployWaitSeconds: 524,
   218  					TargetRepositoryName:  "test",
   219  				},
   220  				generalVerbose: true,
   221  				expectedConfig: []string{"uninstall", "testPackage", "--namespace", "test-namespace", "--wait", "--timeout", "524s", "--debug", "--dry-run"},
   222  			},
   223  		}
   224  
   225  		for _, testCase := range testTable {
   226  			utils := newHelmMockUtilsBundle()
   227  			helmExecute := HelmExecute{
   228  				utils:   utils,
   229  				config:  testCase.config,
   230  				verbose: testCase.generalVerbose,
   231  				stdout:  log.Writer(),
   232  			}
   233  			err := helmExecute.RunHelmUninstall()
   234  			assert.NoError(t, err)
   235  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[1])
   236  		}
   237  	})
   238  
   239  	t.Run("Helm package command", func(t *testing.T) {
   240  		utils := newHelmMockUtilsBundle()
   241  
   242  		testTable := []struct {
   243  			config         HelmExecuteOptions
   244  			expectedConfig []string
   245  		}{
   246  			{
   247  				config: HelmExecuteOptions{
   248  					ChartPath:      ".",
   249  					DeploymentName: "testPackage",
   250  				},
   251  				expectedConfig: []string{"package", "."},
   252  			},
   253  			{
   254  				config: HelmExecuteOptions{
   255  					ChartPath:               ".",
   256  					DeploymentName:          "testPackage",
   257  					Version:                 "1.2.3",
   258  					PackageDependencyUpdate: true,
   259  					AppVersion:              "9.8.7",
   260  				},
   261  				expectedConfig: []string{"package", ".", "--version", "1.2.3", "--dependency-update", "--app-version", "9.8.7"},
   262  			},
   263  		}
   264  
   265  		for i, testCase := range testTable {
   266  			helmExecute := HelmExecute{
   267  				utils:   utils,
   268  				config:  testCase.config,
   269  				verbose: false,
   270  				stdout:  log.Writer(),
   271  			}
   272  			err := helmExecute.runHelmPackage()
   273  			assert.NoError(t, err)
   274  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[i])
   275  		}
   276  	})
   277  
   278  	t.Run("Helm test command", func(t *testing.T) {
   279  		t.Parallel()
   280  		utils := newHelmMockUtilsBundle()
   281  
   282  		testTable := []struct {
   283  			config         HelmExecuteOptions
   284  			expectedConfig []string
   285  		}{
   286  			{
   287  				config: HelmExecuteOptions{
   288  					ChartPath:      ".",
   289  					DeploymentName: "testPackage",
   290  				},
   291  				expectedConfig: []string{"test", "."},
   292  			},
   293  			{
   294  				config: HelmExecuteOptions{
   295  					ChartPath:      ".",
   296  					DeploymentName: "testPackage",
   297  					FilterTest:     "name=test1,name=test2",
   298  					DumpLogs:       true,
   299  				},
   300  				expectedConfig: []string{"test", ".", "--filter", "name=test1,name=test2", "--logs"},
   301  			},
   302  		}
   303  
   304  		for i, testCase := range testTable {
   305  			helmExecute := HelmExecute{
   306  				utils:   utils,
   307  				config:  testCase.config,
   308  				verbose: false,
   309  				stdout:  log.Writer(),
   310  			}
   311  			err := helmExecute.RunHelmTest()
   312  			assert.NoError(t, err)
   313  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[i])
   314  		}
   315  	})
   316  
   317  	t.Run("Helm unistall command(error processing)", func(t *testing.T) {
   318  		t.Parallel()
   319  		utils := newHelmMockUtilsBundle()
   320  
   321  		testTable := []struct {
   322  			config        HelmExecuteOptions
   323  			expectedError error
   324  		}{
   325  			{
   326  				config: HelmExecuteOptions{
   327  					ChartPath:      ".",
   328  					DeploymentName: "testPackage",
   329  				},
   330  				expectedError: errors.New("failed to execute deployments: there is no TargetRepositoryName value. 'helm repo add' command requires 2 arguments"),
   331  			},
   332  			{
   333  				config: HelmExecuteOptions{
   334  					ChartPath:            ".",
   335  					DeploymentName:       "testPackage",
   336  					TargetRepositoryName: "test",
   337  				},
   338  				expectedError: errors.New("namespace has not been set, please configure namespace parameter"),
   339  			},
   340  		}
   341  
   342  		for _, testCase := range testTable {
   343  			helmExecute := HelmExecute{
   344  				utils:   utils,
   345  				config:  testCase.config,
   346  				verbose: false,
   347  				stdout:  log.Writer(),
   348  			}
   349  			err := helmExecute.RunHelmUninstall()
   350  			if testCase.expectedError != nil {
   351  				assert.Error(t, err)
   352  				assert.Equal(t, testCase.expectedError, err)
   353  			}
   354  		}
   355  	})
   356  
   357  	t.Run("Helm init", func(t *testing.T) {
   358  		t.Parallel()
   359  		utils := newHelmMockUtilsBundle()
   360  
   361  		testTable := []struct {
   362  			config        HelmExecuteOptions
   363  			expectedError error
   364  		}{
   365  			{
   366  				config: HelmExecuteOptions{
   367  					ChartPath:      ".",
   368  					Namespace:      "test-namespace",
   369  					DeploymentName: "testPackage",
   370  					KubeContext:    "kubeContext",
   371  					KubeConfig:     "kubeConfig",
   372  				},
   373  				expectedError: nil,
   374  			},
   375  		}
   376  
   377  		for _, testCase := range testTable {
   378  			helmExecute := HelmExecute{
   379  				utils:   utils,
   380  				config:  testCase.config,
   381  				verbose: false,
   382  				stdout:  log.Writer(),
   383  			}
   384  			err := helmExecute.runHelmInit()
   385  			if testCase.expectedError != nil {
   386  				assert.Error(t, err)
   387  				assert.Equal(t, testCase.expectedError, err)
   388  			} else {
   389  				assert.NoError(t, err)
   390  			}
   391  
   392  		}
   393  	})
   394  
   395  	t.Run("Helm dependency command", func(t *testing.T) {
   396  		utils := newHelmMockUtilsBundle()
   397  
   398  		testTable := []struct {
   399  			config         HelmExecuteOptions
   400  			expectedError  error
   401  			expectedResult []string
   402  		}{
   403  			{
   404  				config: HelmExecuteOptions{
   405  					ChartPath: ".",
   406  				},
   407  				expectedError:  errors.New("there is no dependency value. Possible values are build, list, update"),
   408  				expectedResult: nil,
   409  			},
   410  			{
   411  				config: HelmExecuteOptions{
   412  					ChartPath:  ".",
   413  					Dependency: "update",
   414  				},
   415  				expectedError:  nil,
   416  				expectedResult: []string{"dependency", "update", "."},
   417  			},
   418  		}
   419  
   420  		for _, testCase := range testTable {
   421  			helmExecute := HelmExecute{
   422  				utils:   utils,
   423  				config:  testCase.config,
   424  				verbose: false,
   425  				stdout:  log.Writer(),
   426  			}
   427  			err := helmExecute.RunHelmDependency()
   428  			if testCase.expectedError != nil {
   429  				assert.Error(t, err)
   430  				assert.Equal(t, testCase.expectedError, err)
   431  			} else {
   432  				assert.NoError(t, err)
   433  				assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedResult}, utils.Calls[0])
   434  			}
   435  
   436  		}
   437  	})
   438  
   439  	t.Run("Helm publish command", func(t *testing.T) {
   440  		utils := newHelmMockUtilsBundle()
   441  
   442  		config := HelmExecuteOptions{
   443  			TargetRepositoryURL:      "https://my.target.repository.local/",
   444  			TargetRepositoryUser:     "testUser",
   445  			TargetRepositoryPassword: "testPWD",
   446  			PublishVersion:           "1.2.3",
   447  			DeploymentName:           "test_helm_chart",
   448  			ChartPath:                ".",
   449  		}
   450  		utils.ReturnFileUploadStatus = 200
   451  
   452  		helmExecute := HelmExecute{
   453  			utils:   utils,
   454  			config:  config,
   455  			verbose: false,
   456  			stdout:  log.Writer(),
   457  		}
   458  
   459  		err := helmExecute.RunHelmPublish()
   460  		if assert.NoError(t, err) {
   461  			assert.Equal(t, 1, len(utils.FileUploads))
   462  			assert.Equal(t, "https://my.target.repository.local/test_helm_chart/test_helm_chart-1.2.3.tgz", utils.FileUploads["test_helm_chart-1.2.3.tgz"])
   463  		}
   464  	})
   465  
   466  	t.Run("Helm run command", func(t *testing.T) {
   467  		utils := newHelmMockUtilsBundle()
   468  
   469  		testTable := []struct {
   470  			helmParams     []string
   471  			config         HelmExecuteOptions
   472  			expectedConfig []string
   473  		}{
   474  			{
   475  				helmParams: []string{"lint, package, publish"},
   476  				config: HelmExecuteOptions{
   477  					HelmCommand: "lint_package_publish",
   478  				},
   479  				expectedConfig: []string{"lint, package, publish"},
   480  			},
   481  		}
   482  
   483  		for _, testCase := range testTable {
   484  			helmExecute := HelmExecute{
   485  				utils:   utils,
   486  				config:  testCase.config,
   487  				verbose: false,
   488  				stdout:  log.Writer(),
   489  			}
   490  			err := helmExecute.runHelmCommand(testCase.helmParams)
   491  			assert.NoError(t, err)
   492  			assert.Equal(t, mock.ExecCall{Exec: "helm", Params: testCase.expectedConfig}, utils.Calls[0])
   493  		}
   494  
   495  	})
   496  
   497  }