github.com/jaylevin/jenkins-library@v1.230.4/cmd/kubernetesDeploy_test.go (about) 1 package cmd 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "github.com/SAP/jenkins-library/pkg/mock" 9 "github.com/SAP/jenkins-library/pkg/telemetry" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 type kubernetesDeployMockUtils struct { 16 shouldFail bool 17 requestedUrls []string 18 requestedFiles []string 19 *mock.FilesMock 20 *mock.ExecMockRunner 21 *mock.HttpClientMock 22 } 23 24 func newKubernetesDeployMockUtils() kubernetesDeployMockUtils { 25 utils := kubernetesDeployMockUtils{ 26 shouldFail: false, 27 FilesMock: &mock.FilesMock{}, 28 ExecMockRunner: &mock.ExecMockRunner{}, 29 } 30 return utils 31 } 32 33 func TestRunKubernetesDeploy(t *testing.T) { 34 35 t.Run("test helm", func(t *testing.T) { 36 opts := kubernetesDeployOptions{ 37 ContainerRegistryURL: "https://my.registry:55555", 38 ContainerRegistryUser: "registryUser", 39 ContainerRegistryPassword: "dummy", 40 ContainerRegistrySecret: "testSecret", 41 ChartPath: "path/to/chart", 42 DeploymentName: "deploymentName", 43 DeployTool: "helm", 44 ForceUpdates: true, 45 HelmDeployWaitSeconds: 400, 46 IngressHosts: []string{"ingress.host1", "ingress.host2"}, 47 Image: "path/to/Image:latest", 48 AdditionalParameters: []string{"--testParam", "testValue"}, 49 KubeContext: "testCluster", 50 Namespace: "deploymentNamespace", 51 DockerConfigJSON: ".pipeline/docker/config.json", 52 } 53 54 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 55 56 mockUtils := newKubernetesDeployMockUtils() 57 mockUtils.StdoutReturn = map[string]string{ 58 `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, 59 } 60 61 var stdout bytes.Buffer 62 63 telemetryData := &telemetry.CustomData{} 64 65 runKubernetesDeploy(opts, telemetryData, mockUtils, &stdout) 66 67 assert.Equal(t, "helm", mockUtils.Calls[0].Exec, "Wrong init command") 68 assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters") 69 70 assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command") 71 assert.Equal(t, []string{"create", "secret", "generic", "testSecret", "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 72 "--type=kubernetes.io/dockerconfigjson", "--insecure-skip-tls-verify=true", "--dry-run=client", "--output=json"}, 73 mockUtils.Calls[1].Params, "Wrong secret creation parameters") 74 75 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command") 76 assert.Equal(t, []string{ 77 "upgrade", 78 "deploymentName", 79 "path/to/chart", 80 "--install", 81 "--namespace", 82 "deploymentNamespace", 83 "--set", 84 "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", 85 "--force", 86 "--wait", 87 "--timeout", 88 "400", 89 "--atomic", 90 "--kube-context", 91 "testCluster", 92 "--testParam", 93 "testValue", 94 }, mockUtils.Calls[2].Params, "Wrong upgrade parameters") 95 96 assert.Equal(t, &telemetry.CustomData{ 97 Custom1Label: "deployTool", 98 Custom1: "helm", 99 }, telemetryData) 100 }) 101 102 t.Run("test helm - with containerImageName and containerImageTag instead of image", func(t *testing.T) { 103 opts := kubernetesDeployOptions{ 104 ContainerRegistryURL: "https://my.registry:55555", 105 ContainerRegistryUser: "registryUser", 106 ContainerRegistryPassword: "dummy", 107 ContainerRegistrySecret: "testSecret", 108 ChartPath: "path/to/chart", 109 DeploymentName: "deploymentName", 110 DeployTool: "helm", 111 ForceUpdates: true, 112 HelmDeployWaitSeconds: 400, 113 IngressHosts: []string{"ingress.host1", "ingress.host2"}, 114 ContainerImageTag: "latest", 115 ContainerImageName: "path/to/Image", 116 AdditionalParameters: []string{"--testParam", "testValue"}, 117 KubeContext: "testCluster", 118 Namespace: "deploymentNamespace", 119 DockerConfigJSON: ".pipeline/docker/config.json", 120 } 121 122 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 123 124 mockUtils := newKubernetesDeployMockUtils() 125 mockUtils.StdoutReturn = map[string]string{ 126 `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, 127 } 128 129 var stdout bytes.Buffer 130 131 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 132 133 assert.Equal(t, "helm", mockUtils.Calls[0].Exec, "Wrong init command") 134 assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters") 135 136 assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command") 137 assert.Equal(t, []string{ 138 "create", 139 "secret", 140 "generic", 141 "testSecret", 142 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 143 "--type=kubernetes.io/dockerconfigjson", 144 "--insecure-skip-tls-verify=true", 145 "--dry-run=client", 146 "--output=json"}, 147 mockUtils.Calls[1].Params, "Wrong secret creation parameters") 148 149 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command") 150 151 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") 152 }) 153 154 t.Run("test helm - docker config.json path passed as parameter", func(t *testing.T) { 155 opts := kubernetesDeployOptions{ 156 ContainerRegistryURL: "https://my.registry:55555", 157 DockerConfigJSON: "/path/to/.docker/config.json", 158 ContainerRegistryUser: "registryUser", 159 ContainerRegistryPassword: "dummy", 160 ContainerRegistrySecret: "testSecret", 161 ChartPath: "path/to/chart", 162 DeploymentName: "deploymentName", 163 DeployTool: "helm", 164 ForceUpdates: true, 165 HelmDeployWaitSeconds: 400, 166 IngressHosts: []string{"ingress.host1", "ingress.host2"}, 167 Image: "path/to/Image:latest", 168 AdditionalParameters: []string{"--testParam", "testValue"}, 169 KubeContext: "testCluster", 170 Namespace: "deploymentNamespace", 171 } 172 173 k8sSecretSpec := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 174 175 mockUtils := newKubernetesDeployMockUtils() 176 mockUtils.AddFile("/path/to/.docker/config.json", []byte(`{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}`)) 177 mockUtils.StdoutReturn = map[string]string{ 178 `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, 179 } 180 181 var stdout bytes.Buffer 182 183 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 184 assert.NoError(t, err) 185 186 assert.Equal(t, "helm", mockUtils.Calls[0].Exec, "Wrong init command") 187 assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters") 188 189 assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command") 190 assert.Equal(t, []string{ 191 "create", 192 "secret", 193 "generic", 194 "testSecret", 195 "--from-file=.dockerconfigjson=/path/to/.docker/config.json", 196 "--type=kubernetes.io/dockerconfigjson", 197 "--insecure-skip-tls-verify=true", 198 "--dry-run=client", 199 "--output=json"}, 200 mockUtils.Calls[1].Params, "Wrong secret creation parameters") 201 202 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command") 203 assert.Equal(t, []string{ 204 "upgrade", 205 "deploymentName", 206 "path/to/chart", 207 "--install", 208 "--namespace", 209 "deploymentNamespace", 210 "--set", 211 "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", 212 "--force", 213 "--wait", 214 "--timeout", 215 "400", 216 "--atomic", 217 "--kube-context", 218 "testCluster", 219 "--testParam", 220 "testValue", 221 }, mockUtils.Calls[2].Params, "Wrong upgrade parameters") 222 }) 223 224 t.Run("test helm -- keep failed deployment", func(t *testing.T) { 225 opts := kubernetesDeployOptions{ 226 ContainerRegistryURL: "https://my.registry:55555", 227 ContainerRegistryUser: "registryUser", 228 ContainerRegistryPassword: "dummy", 229 ContainerRegistrySecret: "testSecret", 230 ChartPath: "path/to/chart", 231 DeploymentName: "deploymentName", 232 DeployTool: "helm", 233 ForceUpdates: true, 234 HelmDeployWaitSeconds: 400, 235 IngressHosts: []string{"ingress.host1", "ingress.host2"}, 236 Image: "path/to/Image:latest", 237 AdditionalParameters: []string{"--testParam", "testValue"}, 238 KubeContext: "testCluster", 239 Namespace: "deploymentNamespace", 240 KeepFailedDeployments: true, 241 DockerConfigJSON: ".pipeline/docker/config.json", 242 } 243 244 k8sSecretSpec := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 245 246 mockUtils := newKubernetesDeployMockUtils() 247 mockUtils.StdoutReturn = map[string]string{ 248 `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, 249 } 250 251 var stdout bytes.Buffer 252 253 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 254 255 assert.Equal(t, "helm", mockUtils.Calls[0].Exec, "Wrong init command") 256 assert.Equal(t, []string{"init", "--client-only"}, mockUtils.Calls[0].Params, "Wrong init parameters") 257 258 assert.Equal(t, "kubectl", mockUtils.Calls[1].Exec, "Wrong secret creation command") 259 assert.Equal(t, []string{ 260 "create", 261 "secret", 262 "generic", 263 "testSecret", 264 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 265 "--type=kubernetes.io/dockerconfigjson", 266 "--insecure-skip-tls-verify=true", 267 "--dry-run=client", 268 "--output=json"}, 269 mockUtils.Calls[1].Params, "Wrong secret creation parameters") 270 271 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong upgrade command") 272 assert.Equal(t, []string{ 273 "upgrade", 274 "deploymentName", 275 "path/to/chart", 276 "--install", 277 "--namespace", 278 "deploymentNamespace", 279 "--set", 280 "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", 281 "--force", 282 "--wait", 283 "--timeout", 284 "400", 285 "--kube-context", 286 "testCluster", 287 "--testParam", 288 "testValue", 289 }, mockUtils.Calls[2].Params, "Wrong upgrade parameters") 290 }) 291 292 t.Run("test helm - fails without image information", func(t *testing.T) { 293 opts := kubernetesDeployOptions{ 294 ContainerRegistryURL: "https://my.registry:55555", 295 ContainerRegistrySecret: "testSecret", 296 ChartPath: "path/to/chart", 297 DeploymentName: "deploymentName", 298 DeployTool: "helm", 299 ForceUpdates: true, 300 HelmDeployWaitSeconds: 400, 301 IngressHosts: []string{}, 302 AdditionalParameters: []string{"--testParam", "testValue"}, 303 KubeContext: "testCluster", 304 Namespace: "deploymentNamespace", 305 } 306 mockUtils := newKubernetesDeployMockUtils() 307 308 var stdout bytes.Buffer 309 310 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 311 assert.EqualError(t, err, "failed to process deployment values: image information not given - please either set image or containerImageName and containerImageTag") 312 }) 313 314 t.Run("test helm v3", func(t *testing.T) { 315 opts := kubernetesDeployOptions{ 316 ContainerRegistryURL: "https://my.registry:55555", 317 ContainerRegistryUser: "registryUser", 318 ContainerRegistryPassword: "dummy", 319 ContainerRegistrySecret: "testSecret", 320 ChartPath: "path/to/chart", 321 DeploymentName: "deploymentName", 322 DeployTool: "helm3", 323 ForceUpdates: true, 324 HelmDeployWaitSeconds: 400, 325 HelmValues: []string{"values1.yaml", "values2.yaml"}, 326 Image: "path/to/Image:latest", 327 AdditionalParameters: []string{"--testParam", "testValue"}, 328 KubeContext: "testCluster", 329 Namespace: "deploymentNamespace", 330 DockerConfigJSON: ".pipeline/docker/config.json", 331 } 332 333 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 334 335 mockUtils := newKubernetesDeployMockUtils() 336 mockUtils.StdoutReturn = map[string]string{ 337 `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, 338 } 339 340 var stdout bytes.Buffer 341 342 telemetryData := &telemetry.CustomData{} 343 runKubernetesDeploy(opts, telemetryData, mockUtils, &stdout) 344 345 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 346 assert.Equal(t, []string{ 347 "create", 348 "secret", 349 "generic", 350 "testSecret", 351 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 352 "--type=kubernetes.io/dockerconfigjson", 353 "--insecure-skip-tls-verify=true", 354 "--dry-run=client", 355 "--output=json"}, 356 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 357 358 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 359 assert.Equal(t, []string{ 360 "upgrade", 361 "deploymentName", 362 "path/to/chart", 363 "--values", 364 "values1.yaml", 365 "--values", 366 "values2.yaml", 367 "--install", 368 "--namespace", 369 "deploymentNamespace", 370 "--set", 371 "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", 372 "--force", 373 "--wait", 374 "--timeout", 375 "400s", 376 "--atomic", 377 "--kube-context", 378 "testCluster", 379 "--testParam", 380 "testValue", 381 }, mockUtils.Calls[1].Params, "Wrong upgrade parameters") 382 383 assert.Equal(t, &telemetry.CustomData{ 384 Custom1Label: "deployTool", 385 Custom1: "helm3", 386 }, telemetryData) 387 }) 388 389 t.Run("test helm v3 - runs helm tests", func(t *testing.T) { 390 opts := kubernetesDeployOptions{ 391 ContainerRegistryURL: "https://my.registry:55555", 392 ContainerRegistryUser: "registryUser", 393 ContainerRegistryPassword: "dummy", 394 ContainerRegistrySecret: "testSecret", 395 ChartPath: "path/to/chart", 396 DeploymentName: "deploymentName", 397 DeployTool: "helm3", 398 ForceUpdates: true, 399 HelmDeployWaitSeconds: 400, 400 HelmValues: []string{"values1.yaml", "values2.yaml"}, 401 Image: "path/to/Image:latest", 402 AdditionalParameters: []string{"--testParam", "testValue"}, 403 KubeContext: "testCluster", 404 Namespace: "deploymentNamespace", 405 DockerConfigJSON: ".pipeline/docker/config.json", 406 RunHelmTests: true, 407 } 408 409 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 410 411 mockUtils := newKubernetesDeployMockUtils() 412 mockUtils.StdoutReturn = map[string]string{ 413 `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, 414 } 415 416 var stdout bytes.Buffer 417 418 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 419 420 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 421 assert.Equal(t, []string{ 422 "create", 423 "secret", 424 "generic", 425 "testSecret", 426 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 427 "--type=kubernetes.io/dockerconfigjson", 428 "--insecure-skip-tls-verify=true", 429 "--dry-run=client", 430 "--output=json"}, 431 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 432 433 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 434 assert.Equal(t, []string{ 435 "upgrade", 436 "deploymentName", 437 "path/to/chart", 438 "--values", 439 "values1.yaml", 440 "--values", 441 "values2.yaml", 442 "--install", 443 "--namespace", 444 "deploymentNamespace", 445 "--set", 446 "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", 447 "--force", 448 "--wait", 449 "--timeout", 450 "400s", 451 "--atomic", 452 "--kube-context", 453 "testCluster", 454 "--testParam", 455 "testValue", 456 }, mockUtils.Calls[1].Params, "Wrong upgrade parameters") 457 458 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong test command") 459 assert.Equal(t, []string{ 460 "test", 461 "deploymentName", 462 "--namespace", 463 "deploymentNamespace", 464 }, mockUtils.Calls[2].Params, "Wrong test parameters") 465 }) 466 467 t.Run("test helm v3 - runs helm tests with logs", func(t *testing.T) { 468 opts := kubernetesDeployOptions{ 469 ContainerRegistryURL: "https://my.registry:55555", 470 ContainerRegistryUser: "registryUser", 471 ContainerRegistryPassword: "dummy", 472 ContainerRegistrySecret: "testSecret", 473 ChartPath: "path/to/chart", 474 DeploymentName: "deploymentName", 475 DeployTool: "helm3", 476 ForceUpdates: true, 477 HelmDeployWaitSeconds: 400, 478 HelmValues: []string{"values1.yaml", "values2.yaml"}, 479 Image: "path/to/Image:latest", 480 AdditionalParameters: []string{"--testParam", "testValue"}, 481 KubeContext: "testCluster", 482 Namespace: "deploymentNamespace", 483 DockerConfigJSON: ".pipeline/docker/config.json", 484 RunHelmTests: true, 485 ShowTestLogs: true, 486 } 487 488 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 489 490 mockUtils := newKubernetesDeployMockUtils() 491 mockUtils.StdoutReturn = map[string]string{ 492 `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, 493 } 494 495 var stdout bytes.Buffer 496 497 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 498 499 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 500 assert.Equal(t, []string{ 501 "create", 502 "secret", 503 "generic", 504 "testSecret", 505 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 506 "--type=kubernetes.io/dockerconfigjson", 507 "--insecure-skip-tls-verify=true", 508 "--dry-run=client", 509 "--output=json"}, 510 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 511 512 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 513 assert.Equal(t, []string{ 514 "upgrade", 515 "deploymentName", 516 "path/to/chart", 517 "--values", 518 "values1.yaml", 519 "--values", 520 "values2.yaml", 521 "--install", 522 "--namespace", 523 "deploymentNamespace", 524 "--set", 525 "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", 526 "--force", 527 "--wait", 528 "--timeout", 529 "400s", 530 "--atomic", 531 "--kube-context", 532 "testCluster", 533 "--testParam", 534 "testValue", 535 }, mockUtils.Calls[1].Params, "Wrong upgrade parameters") 536 537 assert.Equal(t, "helm", mockUtils.Calls[2].Exec, "Wrong test command") 538 assert.Equal(t, []string{ 539 "test", 540 "deploymentName", 541 "--namespace", 542 "deploymentNamespace", 543 "--logs", 544 }, mockUtils.Calls[2].Params, "Wrong test parameters") 545 }) 546 547 t.Run("test helm v3 - should not run helm tests", func(t *testing.T) { 548 opts := kubernetesDeployOptions{ 549 ContainerRegistryURL: "https://my.registry:55555", 550 ContainerRegistryUser: "registryUser", 551 ContainerRegistryPassword: "dummy", 552 ContainerRegistrySecret: "testSecret", 553 ChartPath: "path/to/chart", 554 DeploymentName: "deploymentName", 555 DeployTool: "helm3", 556 ForceUpdates: true, 557 HelmDeployWaitSeconds: 400, 558 HelmValues: []string{"values1.yaml", "values2.yaml"}, 559 Image: "path/to/Image:latest", 560 AdditionalParameters: []string{"--testParam", "testValue"}, 561 KubeContext: "testCluster", 562 Namespace: "deploymentNamespace", 563 DockerConfigJSON: ".pipeline/docker/config.json", 564 RunHelmTests: false, 565 ShowTestLogs: true, 566 } 567 568 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 569 570 mockUtils := newKubernetesDeployMockUtils() 571 mockUtils.StdoutReturn = map[string]string{ 572 `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, 573 } 574 575 var stdout bytes.Buffer 576 577 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 578 579 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 580 assert.Equal(t, []string{ 581 "create", 582 "secret", 583 "generic", 584 "testSecret", 585 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 586 "--type=kubernetes.io/dockerconfigjson", 587 "--insecure-skip-tls-verify=true", 588 "--dry-run=client", 589 "--output=json"}, 590 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 591 592 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 593 assert.Equal(t, []string{ 594 "upgrade", 595 "deploymentName", 596 "path/to/chart", 597 "--values", 598 "values1.yaml", 599 "--values", 600 "values2.yaml", 601 "--install", 602 "--namespace", 603 "deploymentNamespace", 604 "--set", 605 "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", 606 "--force", 607 "--wait", 608 "--timeout", 609 "400s", 610 "--atomic", 611 "--kube-context", 612 "testCluster", 613 "--testParam", 614 "testValue", 615 }, mockUtils.Calls[1].Params, "Wrong upgrade parameters") 616 617 assert.Equal(t, 2, len(mockUtils.Calls), "Too many helm calls") 618 }) 619 620 t.Run("test helm v3 - with containerImageName and containerImageTag instead of image", func(t *testing.T) { 621 opts := kubernetesDeployOptions{ 622 ContainerRegistryURL: "https://my.registry:55555", 623 ContainerRegistryUser: "registryUser", 624 ContainerRegistryPassword: "dummy", 625 ContainerRegistrySecret: "testSecret", 626 ChartPath: "path/to/chart", 627 DeploymentName: "deploymentName", 628 DeployTool: "helm3", 629 ForceUpdates: true, 630 HelmDeployWaitSeconds: 400, 631 HelmValues: []string{"values1.yaml", "values2.yaml"}, 632 ContainerImageName: "path/to/Image", 633 ContainerImageTag: "latest", 634 AdditionalParameters: []string{"--testParam", "testValue"}, 635 KubeContext: "testCluster", 636 Namespace: "deploymentNamespace", 637 DockerConfigJSON: ".pipeline/docker/config.json", 638 } 639 640 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 641 642 mockUtils := newKubernetesDeployMockUtils() 643 mockUtils.StdoutReturn = map[string]string{ 644 `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, 645 } 646 647 var stdout bytes.Buffer 648 649 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 650 651 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 652 assert.Equal(t, []string{ 653 "create", 654 "secret", 655 "generic", 656 "testSecret", 657 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 658 "--type=kubernetes.io/dockerconfigjson", 659 "--insecure-skip-tls-verify=true", 660 "--dry-run=client", 661 "--output=json"}, 662 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 663 664 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 665 666 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") 667 668 }) 669 670 t.Run("test helm v3 - with multiple images", func(t *testing.T) { 671 opts := kubernetesDeployOptions{ 672 ContainerRegistryURL: "https://my.registry:55555", 673 ContainerRegistryUser: "registryUser", 674 ContainerRegistryPassword: "dummy", 675 ContainerRegistrySecret: "testSecret", 676 ChartPath: "path/to/chart", 677 DeploymentName: "deploymentName", 678 DeployTool: "helm3", 679 ForceUpdates: true, 680 HelmDeployWaitSeconds: 400, 681 HelmValues: []string{"values1.yaml", "values2.yaml"}, 682 ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, 683 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 684 AdditionalParameters: []string{"--testParam", "testValue"}, 685 KubeContext: "testCluster", 686 Namespace: "deploymentNamespace", 687 DockerConfigJSON: ".pipeline/docker/config.json", 688 } 689 690 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 691 692 mockUtils := newKubernetesDeployMockUtils() 693 mockUtils.StdoutReturn = map[string]string{ 694 `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, 695 } 696 697 var stdout bytes.Buffer 698 699 require.NoError(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout)) 700 701 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 702 assert.Equal(t, []string{ 703 "create", 704 "secret", 705 "generic", 706 "testSecret", 707 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 708 "--type=kubernetes.io/dockerconfigjson", 709 "--insecure-skip-tls-verify=true", 710 "--dry-run=client", 711 "--output=json"}, 712 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 713 714 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 715 716 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") 717 718 }) 719 720 t.Run("test helm v3 - with one image in multiple images array", func(t *testing.T) { 721 opts := kubernetesDeployOptions{ 722 ContainerRegistryURL: "https://my.registry:55555", 723 ContainerRegistryUser: "registryUser", 724 ContainerRegistryPassword: "dummy", 725 ContainerRegistrySecret: "testSecret", 726 ChartPath: "path/to/chart", 727 DeploymentName: "deploymentName", 728 DeployTool: "helm3", 729 ForceUpdates: true, 730 HelmDeployWaitSeconds: 400, 731 HelmValues: []string{"values1.yaml", "values2.yaml"}, 732 ImageNames: []string{"myImage"}, 733 ImageNameTags: []string{"myImage:myTag"}, 734 AdditionalParameters: []string{"--testParam", "testValue"}, 735 KubeContext: "testCluster", 736 Namespace: "deploymentNamespace", 737 DockerConfigJSON: ".pipeline/docker/config.json", 738 } 739 740 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 741 742 mockUtils := newKubernetesDeployMockUtils() 743 mockUtils.StdoutReturn = map[string]string{ 744 `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, 745 } 746 747 var stdout bytes.Buffer 748 749 require.NoError(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout)) 750 751 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 752 assert.Equal(t, []string{ 753 "create", 754 "secret", 755 "generic", 756 "testSecret", 757 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 758 "--type=kubernetes.io/dockerconfigjson", 759 "--insecure-skip-tls-verify=true", 760 "--dry-run=client", 761 "--output=json"}, 762 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 763 764 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 765 766 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") 767 768 }) 769 770 t.Run("test helm v3 - with multiple images - missing ImageNameTags", func(t *testing.T) { 771 opts := kubernetesDeployOptions{ 772 ContainerRegistryURL: "https://my.registry:55555", 773 ContainerRegistryUser: "registryUser", 774 ContainerRegistryPassword: "dummy", 775 ContainerRegistrySecret: "testSecret", 776 ChartPath: "path/to/chart", 777 DeploymentName: "deploymentName", 778 DeployTool: "helm3", 779 ForceUpdates: true, 780 HelmDeployWaitSeconds: 400, 781 HelmValues: []string{"values1.yaml", "values2.yaml"}, 782 ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, 783 ImageNameTags: []string{"myImage:myTag"}, 784 AdditionalParameters: []string{"--testParam", "testValue"}, 785 KubeContext: "testCluster", 786 Namespace: "deploymentNamespace", 787 DockerConfigJSON: ".pipeline/docker/config.json", 788 } 789 790 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 791 792 mockUtils := newKubernetesDeployMockUtils() 793 mockUtils.StdoutReturn = map[string]string{ 794 `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, 795 } 796 797 var stdout bytes.Buffer 798 799 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 800 assert.EqualError(t, err, "failed to process deployment values: number of imageNames and imageNameTags must be equal") 801 }) 802 803 t.Run("test helm v3 - with multiple images and valuesMapping", func(t *testing.T) { 804 opts := kubernetesDeployOptions{ 805 ContainerRegistryURL: "https://my.registry:55555", 806 ContainerRegistryUser: "registryUser", 807 ContainerRegistryPassword: "dummy", 808 ContainerRegistrySecret: "testSecret", 809 ChartPath: "path/to/chart", 810 DeploymentName: "deploymentName", 811 DeployTool: "helm3", 812 ForceUpdates: true, 813 HelmDeployWaitSeconds: 400, 814 HelmValues: []string{"values1.yaml", "values2.yaml"}, 815 ValuesMapping: map[string]interface{}{ 816 "subchart.image.registry": "image.myImage.repository", 817 "subchart.image.tag": "image.myImage.tag", 818 }, 819 ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, 820 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 821 AdditionalParameters: []string{"--testParam", "testValue"}, 822 KubeContext: "testCluster", 823 Namespace: "deploymentNamespace", 824 DockerConfigJSON: ".pipeline/docker/config.json", 825 } 826 827 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 828 829 mockUtils := newKubernetesDeployMockUtils() 830 mockUtils.StdoutReturn = map[string]string{ 831 `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, 832 } 833 834 var stdout bytes.Buffer 835 836 require.NoError(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout)) 837 838 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 839 assert.Equal(t, []string{ 840 "create", 841 "secret", 842 "generic", 843 "testSecret", 844 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 845 "--type=kubernetes.io/dockerconfigjson", 846 "--insecure-skip-tls-verify=true", 847 "--dry-run=client", 848 "--output=json"}, 849 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 850 851 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 852 assert.Equal(t, len(mockUtils.Calls[1].Params), 21, "Unexpected upgrade command") 853 pos := 11 854 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage.repository=my.registry:55555/myImage", "Missing update parameter") 855 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage.tag=myTag", "Wrong upgrade parameters") 856 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage_sub1.repository=my.registry:55555/myImage-sub1", "Missing update parameter") 857 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage_sub1.tag=myTag", "Missing update parameter") 858 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage_sub2.repository=my.registry:55555/myImage-sub2", "Missing update parameter") 859 assert.Contains(t, mockUtils.Calls[1].Params[pos], "image.myImage_sub2.tag=myTag,secret.name=testSecret,secret.dockerconfigjson=ThisIsOurBase64EncodedSecret==", "Missing update parameter") 860 assert.Contains(t, mockUtils.Calls[1].Params[pos], "imagePullSecrets[0].name=testSecret", "Missing update parameter") 861 assert.Contains(t, mockUtils.Calls[1].Params[pos], "subchart.image.registry=my.registry:55555/myImage", "Missing update parameter") 862 assert.Contains(t, mockUtils.Calls[1].Params[pos], "subchart.image.tag=myTag", "Missing update parameter") 863 }) 864 865 t.Run("test helm v3 - with multiple images and incorrect valuesMapping", func(t *testing.T) { 866 opts := kubernetesDeployOptions{ 867 ContainerRegistryURL: "https://my.registry:55555", 868 ContainerRegistryUser: "registryUser", 869 ContainerRegistryPassword: "dummy", 870 ContainerRegistrySecret: "testSecret", 871 ChartPath: "path/to/chart", 872 DeploymentName: "deploymentName", 873 DeployTool: "helm3", 874 ForceUpdates: true, 875 HelmDeployWaitSeconds: 400, 876 HelmValues: []string{"values1.yaml", "values2.yaml"}, 877 ValuesMapping: map[string]interface{}{ 878 "subchart.image.registry": false, 879 }, 880 ImageNames: []string{"myImage", "myImage.sub1", "myImage.sub2"}, 881 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 882 AdditionalParameters: []string{"--testParam", "testValue"}, 883 KubeContext: "testCluster", 884 Namespace: "deploymentNamespace", 885 DockerConfigJSON: ".pipeline/docker/config.json", 886 } 887 888 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 889 890 mockUtils := newKubernetesDeployMockUtils() 891 mockUtils.StdoutReturn = map[string]string{ 892 `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, 893 } 894 895 var stdout bytes.Buffer 896 897 require.Error(t, runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout), "invalid path 'false' is used for valueMapping, only strings are supported") 898 899 }) 900 901 t.Run("test helm3 - fails without image information", func(t *testing.T) { 902 opts := kubernetesDeployOptions{ 903 ContainerRegistryURL: "https://my.registry:55555", 904 ContainerRegistrySecret: "testSecret", 905 ChartPath: "path/to/chart", 906 DeploymentName: "deploymentName", 907 DeployTool: "helm3", 908 ForceUpdates: true, 909 HelmDeployWaitSeconds: 400, 910 IngressHosts: []string{}, 911 AdditionalParameters: []string{"--testParam", "testValue"}, 912 KubeContext: "testCluster", 913 Namespace: "deploymentNamespace", 914 } 915 mockUtils := newKubernetesDeployMockUtils() 916 917 var stdout bytes.Buffer 918 919 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 920 assert.EqualError(t, err, "failed to process deployment values: image information not given - please either set image or containerImageName and containerImageTag") 921 }) 922 923 t.Run("test helm v3 - keep failed deployments", func(t *testing.T) { 924 opts := kubernetesDeployOptions{ 925 ContainerRegistryURL: "https://my.registry:55555", 926 ContainerRegistryUser: "registryUser", 927 ContainerRegistryPassword: "dummy", 928 ContainerRegistrySecret: "testSecret", 929 ChartPath: "path/to/chart", 930 DeploymentName: "deploymentName", 931 DeployTool: "helm3", 932 ForceUpdates: true, 933 HelmDeployWaitSeconds: 400, 934 HelmValues: []string{"values1.yaml", "values2.yaml"}, 935 Image: "path/to/Image:latest", 936 AdditionalParameters: []string{"--testParam", "testValue"}, 937 KubeContext: "testCluster", 938 Namespace: "deploymentNamespace", 939 KeepFailedDeployments: true, 940 DockerConfigJSON: ".pipeline/docker/config.json", 941 } 942 943 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 944 945 mockUtils := newKubernetesDeployMockUtils() 946 mockUtils.StdoutReturn = map[string]string{ 947 `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, 948 } 949 950 var stdout bytes.Buffer 951 952 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 953 954 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong secret creation command") 955 assert.Equal(t, []string{ 956 "create", 957 "secret", 958 "generic", 959 "testSecret", 960 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 961 "--type=kubernetes.io/dockerconfigjson", 962 "--insecure-skip-tls-verify=true", 963 "--dry-run=client", 964 "--output=json"}, 965 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 966 967 assert.Equal(t, "helm", mockUtils.Calls[1].Exec, "Wrong upgrade command") 968 assert.Equal(t, []string{ 969 "upgrade", 970 "deploymentName", 971 "path/to/chart", 972 "--values", 973 "values1.yaml", 974 "--values", 975 "values2.yaml", 976 "--install", 977 "--namespace", 978 "deploymentNamespace", 979 "--set", 980 "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", 981 "--force", 982 "--wait", 983 "--timeout", 984 "400s", 985 "--kube-context", 986 "testCluster", 987 "--testParam", 988 "testValue", 989 }, mockUtils.Calls[1].Params, "Wrong upgrade parameters") 990 }) 991 992 t.Run("test helm v3 - no container credentials", func(t *testing.T) { 993 opts := kubernetesDeployOptions{ 994 ContainerRegistryURL: "https://my.registry:55555", 995 ChartPath: "path/to/chart", 996 ContainerRegistrySecret: "testSecret", 997 DeploymentName: "deploymentName", 998 DeployTool: "helm3", 999 ForceUpdates: true, 1000 HelmDeployWaitSeconds: 400, 1001 IngressHosts: []string{}, 1002 Image: "path/to/Image:latest", 1003 AdditionalParameters: []string{"--testParam", "testValue"}, 1004 KubeContext: "testCluster", 1005 Namespace: "deploymentNamespace", 1006 } 1007 mockUtils := newKubernetesDeployMockUtils() 1008 1009 var stdout bytes.Buffer 1010 1011 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1012 1013 assert.Equal(t, 1, len(mockUtils.Calls), "Wrong number of upgrade commands") 1014 assert.Equal(t, "helm", mockUtils.Calls[0].Exec, "Wrong upgrade command") 1015 assert.Equal(t, []string{ 1016 "upgrade", 1017 "deploymentName", 1018 "path/to/chart", 1019 "--install", 1020 "--namespace", 1021 "deploymentNamespace", 1022 "--set", 1023 "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", 1024 "--force", 1025 "--wait", 1026 "--timeout", 1027 "400s", 1028 "--atomic", 1029 "--kube-context", 1030 "testCluster", 1031 "--testParam", 1032 "testValue", 1033 }, mockUtils.Calls[0].Params, "Wrong upgrade parameters") 1034 }) 1035 1036 t.Run("test helm v3 - fails without chart path", func(t *testing.T) { 1037 opts := kubernetesDeployOptions{ 1038 ContainerRegistryURL: "https://my.registry:55555", 1039 ContainerRegistrySecret: "testSecret", 1040 DeploymentName: "deploymentName", 1041 DeployTool: "helm3", 1042 ForceUpdates: true, 1043 HelmDeployWaitSeconds: 400, 1044 IngressHosts: []string{}, 1045 Image: "path/to/Image:latest", 1046 AdditionalParameters: []string{"--testParam", "testValue"}, 1047 KubeContext: "testCluster", 1048 Namespace: "deploymentNamespace", 1049 } 1050 mockUtils := newKubernetesDeployMockUtils() 1051 1052 var stdout bytes.Buffer 1053 1054 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1055 assert.EqualError(t, err, "chart path has not been set, please configure chartPath parameter") 1056 }) 1057 1058 t.Run("test helm v3 - fails without deployment name", func(t *testing.T) { 1059 opts := kubernetesDeployOptions{ 1060 ContainerRegistryURL: "https://my.registry:55555", 1061 ContainerRegistrySecret: "testSecret", 1062 ChartPath: "path/to/chart", 1063 DeployTool: "helm3", 1064 ForceUpdates: true, 1065 HelmDeployWaitSeconds: 400, 1066 IngressHosts: []string{}, 1067 Image: "path/to/Image:latest", 1068 AdditionalParameters: []string{"--testParam", "testValue"}, 1069 KubeContext: "testCluster", 1070 Namespace: "deploymentNamespace", 1071 } 1072 mockUtils := newKubernetesDeployMockUtils() 1073 1074 var stdout bytes.Buffer 1075 1076 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1077 assert.EqualError(t, err, "deployment name has not been set, please configure deploymentName parameter") 1078 }) 1079 1080 t.Run("test helm v3 - no force", func(t *testing.T) { 1081 opts := kubernetesDeployOptions{ 1082 ContainerRegistryURL: "https://my.registry:55555", 1083 ChartPath: "path/to/chart", 1084 ContainerRegistrySecret: "testSecret", 1085 DeploymentName: "deploymentName", 1086 DeployTool: "helm3", 1087 HelmDeployWaitSeconds: 400, 1088 IngressHosts: []string{}, 1089 Image: "path/to/Image:latest", 1090 AdditionalParameters: []string{"--testParam", "testValue"}, 1091 KubeContext: "testCluster", 1092 Namespace: "deploymentNamespace", 1093 } 1094 mockUtils := newKubernetesDeployMockUtils() 1095 1096 var stdout bytes.Buffer 1097 1098 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1099 assert.Equal(t, []string{ 1100 "upgrade", 1101 "deploymentName", 1102 "path/to/chart", 1103 "--install", 1104 "--namespace", 1105 "deploymentNamespace", 1106 "--set", 1107 "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", 1108 "--wait", 1109 "--timeout", 1110 "400s", 1111 "--atomic", 1112 "--kube-context", 1113 "testCluster", 1114 "--testParam", 1115 "testValue", 1116 }, mockUtils.Calls[0].Params, "Wrong upgrade parameters") 1117 }) 1118 1119 t.Run("test kubectl - create secret from docker config.json", func(t *testing.T) { 1120 1121 opts := kubernetesDeployOptions{ 1122 AppTemplate: "path/to/test.yaml", 1123 ContainerRegistryURL: "https://my.registry:55555", 1124 ContainerRegistryUser: "registryUser", 1125 ContainerRegistryPassword: "dummy", 1126 ContainerRegistrySecret: "regSecret", 1127 CreateDockerRegistrySecret: true, 1128 DeployTool: "kubectl", 1129 Image: "path/to/Image:latest", 1130 AdditionalParameters: []string{"--testParam", "testValue"}, 1131 KubeConfig: "This is my kubeconfig", 1132 KubeContext: "testCluster", 1133 Namespace: "deploymentNamespace", 1134 DeployCommand: "apply", 1135 DockerConfigJSON: ".pipeline/docker/config.json", 1136 } 1137 1138 kubeYaml := `kind: Deployment 1139 metadata: 1140 spec: 1141 spec: 1142 image: <image-name>` 1143 1144 dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` 1145 1146 mockUtils := newKubernetesDeployMockUtils() 1147 mockUtils.AddFile(opts.AppTemplate, []byte(kubeYaml)) 1148 1149 mockUtils.StdoutReturn = map[string]string{ 1150 `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, 1151 } 1152 var stdout bytes.Buffer 1153 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1154 1155 assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"}) 1156 1157 assert.Equal(t, []string{ 1158 "create", 1159 "secret", 1160 "generic", 1161 "regSecret", 1162 "--from-file=.dockerconfigjson=.pipeline/docker/config.json", 1163 "--type=kubernetes.io/dockerconfigjson", 1164 "--insecure-skip-tls-verify=true", 1165 "--dry-run=client", 1166 "--output=json", 1167 "--insecure-skip-tls-verify=true", 1168 "--namespace=deploymentNamespace", 1169 "--context=testCluster", 1170 }, 1171 mockUtils.Calls[0].Params, "Wrong secret creation parameters") 1172 1173 assert.Containsf(t, mockUtils.Calls[1].Params, "apply", "Wrong secret creation parameters") 1174 assert.Containsf(t, mockUtils.Calls[1].Params, "-f", "Wrong secret creation parameters") 1175 }) 1176 1177 t.Run("test kubectl - token only", func(t *testing.T) { 1178 1179 opts := kubernetesDeployOptions{ 1180 APIServer: "https://my.api.server", 1181 AppTemplate: "path/to/test.yaml", 1182 ContainerRegistryURL: "https://my.registry:55555", 1183 ContainerRegistrySecret: "regSecret", 1184 DeployTool: "kubectl", 1185 Image: "path/to/Image:latest", 1186 KubeToken: "testToken", 1187 Namespace: "deploymentNamespace", 1188 DeployCommand: "apply", 1189 } 1190 1191 mockUtils := newKubernetesDeployMockUtils() 1192 mockUtils.AddFile(opts.AppTemplate, []byte("testYaml")) 1193 mockUtils.ShouldFailOnCommand = map[string]error{} 1194 1195 var stdout bytes.Buffer 1196 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1197 1198 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong apply command") 1199 assert.Equal(t, []string{ 1200 "--insecure-skip-tls-verify=true", 1201 fmt.Sprintf("--namespace=%v", opts.Namespace), 1202 fmt.Sprintf("--server=%v", opts.APIServer), 1203 fmt.Sprintf("--token=%v", opts.KubeToken), 1204 "apply", 1205 "--filename", 1206 opts.AppTemplate, 1207 }, mockUtils.Calls[0].Params, "kubectl parameters incorrect") 1208 }) 1209 1210 t.Run("test kubectl - with containerImageName and containerImageTag instead of image", func(t *testing.T) { 1211 opts := kubernetesDeployOptions{ 1212 APIServer: "https://my.api.server", 1213 AppTemplate: "test.yaml", 1214 ContainerRegistryURL: "https://my.registry:55555", 1215 ContainerRegistrySecret: "regSecret", 1216 DeployTool: "kubectl", 1217 ContainerImageTag: "latest", 1218 ContainerImageName: "path/to/Image", 1219 KubeConfig: "This is my kubeconfig", 1220 Namespace: "deploymentNamespace", 1221 DeployCommand: "apply", 1222 } 1223 1224 mockUtils := newKubernetesDeployMockUtils() 1225 mockUtils.AddFile("test.yaml", []byte("image: <image-name>")) 1226 1227 var stdout bytes.Buffer 1228 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1229 1230 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong apply command") 1231 1232 appTemplateFileContents, err := mockUtils.FileRead(opts.AppTemplate) 1233 assert.NoError(t, err) 1234 assert.Contains(t, string(appTemplateFileContents), "image: my.registry:55555/path/to/Image:latest", "kubectl parameters incorrect") 1235 }) 1236 1237 t.Run("test kubectl - with containerImageName and containerImageTag instead of image using go template", func(t *testing.T) { 1238 opts := kubernetesDeployOptions{ 1239 APIServer: "https://my.api.server", 1240 AppTemplate: "test.yaml", 1241 ContainerRegistryURL: "https://my.registry:55555", 1242 ContainerRegistrySecret: "regSecret", 1243 DeployTool: "kubectl", 1244 ContainerImageTag: "latest", 1245 ContainerImageName: "path/to/Image", 1246 KubeConfig: "This is my kubeconfig", 1247 Namespace: "deploymentNamespace", 1248 DeployCommand: "apply", 1249 } 1250 1251 mockUtils := newKubernetesDeployMockUtils() 1252 mockUtils.AddFile("test.yaml", []byte("image: {{ .Values.image.repository }}:{{ .Values.image.tag }}")) 1253 1254 var stdout bytes.Buffer 1255 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1256 1257 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong apply command") 1258 1259 appTemplateFileContents, err := mockUtils.FileRead(opts.AppTemplate) 1260 assert.NoError(t, err) 1261 assert.Contains(t, string(appTemplateFileContents), "image: my.registry:55555/path/to/Image:latest", "kubectl parameters incorrect") 1262 }) 1263 1264 t.Run("test kubectl - with multiple images using go template", func(t *testing.T) { 1265 opts := kubernetesDeployOptions{ 1266 APIServer: "https://my.api.server", 1267 AppTemplate: "test.yaml", 1268 ContainerRegistryURL: "https://my.registry:55555", 1269 ContainerRegistrySecret: "regSecret", 1270 DeployTool: "kubectl", 1271 KubeConfig: "This is my kubeconfig", 1272 Namespace: "deploymentNamespace", 1273 DeployCommand: "apply", 1274 ValuesMapping: map[string]interface{}{ 1275 "subchart.image.repository": "image.myImage.repository", 1276 "subchart.image.tag": "image.myImage.tag", 1277 }, 1278 ImageNames: []string{"myImage", "myImage-sub1", "myImage-sub2"}, 1279 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 1280 } 1281 1282 mockUtils := newKubernetesDeployMockUtils() 1283 mockUtils.AddFile("test.yaml", []byte(`image: {{ .Values.image.myImage.repository }}:{{ .Values.image.myImage.tag }} 1284 image2: {{ .Values.subchart.image.repository }}:{{ .Values.subchart.image.tag }} 1285 image3: {{ .Values.image.myImage_sub1.repository }}:{{ .Values.image.myImage_sub1.tag }}`)) 1286 1287 var stdout bytes.Buffer 1288 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1289 1290 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong apply command") 1291 1292 appTemplateFileContents, err := mockUtils.FileRead(opts.AppTemplate) 1293 assert.NoError(t, err) 1294 assert.Contains(t, string(appTemplateFileContents), "image: my.registry:55555/myImage:myTag\nimage2: my.registry:55555/myImage:myTag\nimage3: my.registry:55555/myImage-sub1:myTag", "kubectl parameters incorrect") 1295 }) 1296 1297 t.Run("test kubectl - with multiple images and digests", func(t *testing.T) { 1298 opts := kubernetesDeployOptions{ 1299 APIServer: "https://my.api.server", 1300 AppTemplate: "test.yaml", 1301 ContainerRegistryURL: "https://my.registry:55555", 1302 ContainerRegistrySecret: "regSecret", 1303 DeployTool: "kubectl", 1304 KubeConfig: "This is my kubeconfig", 1305 Namespace: "deploymentNamespace", 1306 DeployCommand: "apply", 1307 ValuesMapping: map[string]interface{}{ 1308 "subchart.image.repository": "image.myImage.repository", 1309 "subchart.image.tag": "image.myImage.tag", 1310 }, 1311 ImageNames: []string{"myImage", "myImage-sub1", "myImage-sub2"}, 1312 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 1313 ImageDigests: []string{"sha256:111", "sha256:222", "sha256:333"}, 1314 } 1315 1316 mockUtils := newKubernetesDeployMockUtils() 1317 mockUtils.AddFile("test.yaml", []byte(`image: {{ .Values.image.myImage.repository }}:{{ .Values.image.myImage.tag }} 1318 image2: {{ .Values.subchart.image.repository }}:{{ .Values.subchart.image.tag }} 1319 image3: {{ .Values.image.myImage_sub1.repository }}:{{ .Values.image.myImage_sub1.tag }} 1320 image4: {{ .Values.image.myImage_sub2.repository }}:{{ .Values.image.myImage_sub2.tag }}`)) 1321 1322 var stdout bytes.Buffer 1323 runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1324 1325 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong apply command") 1326 1327 appTemplateFileContents, err := mockUtils.FileRead(opts.AppTemplate) 1328 assert.NoError(t, err) 1329 assert.Contains(t, string(appTemplateFileContents), `image: my.registry:55555/myImage:myTag@sha256:111 1330 image2: my.registry:55555/myImage:myTag@sha256:111 1331 image3: my.registry:55555/myImage-sub1:myTag@sha256:222 1332 image4: my.registry:55555/myImage-sub2:myTag@sha256:333`, "kubectl parameters incorrect") 1333 }) 1334 1335 t.Run("test kubectl - fail with multiple images using placeholder", func(t *testing.T) { 1336 opts := kubernetesDeployOptions{ 1337 APIServer: "https://my.api.server", 1338 AppTemplate: "test.yaml", 1339 ContainerRegistryURL: "https://my.registry:55555", 1340 ContainerRegistrySecret: "regSecret", 1341 DeployTool: "kubectl", 1342 KubeConfig: "This is my kubeconfig", 1343 Namespace: "deploymentNamespace", 1344 DeployCommand: "apply", 1345 ImageNames: []string{"myImage", "myImage-sub1", "myImage-sub2"}, 1346 ImageNameTags: []string{"myImage:myTag", "myImage-sub1:myTag", "myImage-sub2:myTag"}, 1347 } 1348 1349 mockUtils := newKubernetesDeployMockUtils() 1350 mockUtils.AddFile("test.yaml", []byte("image: <image-name>")) 1351 1352 var stdout bytes.Buffer 1353 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1354 assert.EqualError(t, err, "multi-image replacement not supported for single image placeholder") 1355 }) 1356 1357 t.Run("test kubectl - fails without image information", func(t *testing.T) { 1358 opts := kubernetesDeployOptions{ 1359 APIServer: "https://my.api.server", 1360 AppTemplate: "test.yaml", 1361 ContainerRegistryURL: "https://my.registry:55555", 1362 ContainerRegistrySecret: "regSecret", 1363 DeployTool: "kubectl", 1364 KubeConfig: "This is my kubeconfig", 1365 Namespace: "deploymentNamespace", 1366 DeployCommand: "apply", 1367 } 1368 1369 mockUtils := newKubernetesDeployMockUtils() 1370 mockUtils.AddFile("test.yaml", []byte("testYaml")) 1371 1372 var stdout bytes.Buffer 1373 1374 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1375 assert.EqualError(t, err, "failed to process deployment values: image information not given - please either set image or containerImageName and containerImageTag") 1376 }) 1377 1378 t.Run("test kubectl - use replace deploy command", func(t *testing.T) { 1379 opts := kubernetesDeployOptions{ 1380 AppTemplate: "test.yaml", 1381 ContainerRegistryURL: "https://my.registry:55555", 1382 ContainerRegistrySecret: "regSecret", 1383 CreateDockerRegistrySecret: true, 1384 DeployTool: "kubectl", 1385 Image: "path/to/Image:latest", 1386 AdditionalParameters: []string{"--testParam", "testValue"}, 1387 KubeConfig: "This is my kubeconfig", 1388 KubeContext: "testCluster", 1389 Namespace: "deploymentNamespace", 1390 DeployCommand: "replace", 1391 } 1392 1393 kubeYaml := `kind: Deployment 1394 metadata: 1395 spec: 1396 spec: 1397 image: <image-name>` 1398 1399 mockUtils := newKubernetesDeployMockUtils() 1400 mockUtils.AddFile("test.yaml", []byte(kubeYaml)) 1401 1402 var stdout bytes.Buffer 1403 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1404 assert.NoError(t, err, "Command should not fail") 1405 1406 assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"}) 1407 1408 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong replace command") 1409 assert.Equal(t, []string{ 1410 "--insecure-skip-tls-verify=true", 1411 fmt.Sprintf("--namespace=%v", opts.Namespace), 1412 fmt.Sprintf("--context=%v", opts.KubeContext), 1413 "replace", 1414 "--filename", 1415 opts.AppTemplate, 1416 "--testParam", 1417 "testValue", 1418 }, mockUtils.Calls[0].Params, "kubectl parameters incorrect") 1419 1420 appTemplate, err := mockUtils.FileRead(opts.AppTemplate) 1421 assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest") 1422 }) 1423 1424 t.Run("test kubectl - use replace --force deploy command", func(t *testing.T) { 1425 opts := kubernetesDeployOptions{ 1426 AppTemplate: "test.yaml", 1427 ContainerRegistryURL: "https://my.registry:55555", 1428 ContainerRegistrySecret: "regSecret", 1429 CreateDockerRegistrySecret: true, 1430 DeployTool: "kubectl", 1431 Image: "path/to/Image:latest", 1432 AdditionalParameters: []string{"--testParam", "testValue"}, 1433 KubeConfig: "This is my kubeconfig", 1434 KubeContext: "testCluster", 1435 Namespace: "deploymentNamespace", 1436 DeployCommand: "replace", 1437 ForceUpdates: true, 1438 } 1439 1440 kubeYaml := `kind: Deployment 1441 metadata: 1442 spec: 1443 spec: 1444 image: <image-name>` 1445 1446 mockUtils := newKubernetesDeployMockUtils() 1447 mockUtils.AddFile("test.yaml", []byte(kubeYaml)) 1448 1449 var stdout bytes.Buffer 1450 err := runKubernetesDeploy(opts, &telemetry.CustomData{}, mockUtils, &stdout) 1451 assert.NoError(t, err, "Command should not fail") 1452 1453 assert.Equal(t, mockUtils.Env, []string{"KUBECONFIG=This is my kubeconfig"}) 1454 1455 assert.Equal(t, "kubectl", mockUtils.Calls[0].Exec, "Wrong replace command") 1456 assert.Equal(t, []string{ 1457 "--insecure-skip-tls-verify=true", 1458 fmt.Sprintf("--namespace=%v", opts.Namespace), 1459 fmt.Sprintf("--context=%v", opts.KubeContext), 1460 "replace", 1461 "--filename", 1462 opts.AppTemplate, 1463 "--force", 1464 "--testParam", 1465 "testValue", 1466 }, mockUtils.Calls[0].Params, "kubectl parameters incorrect") 1467 1468 appTemplate, err := mockUtils.FileRead(opts.AppTemplate) 1469 assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest") 1470 }) 1471 1472 } 1473 1474 func TestSplitRegistryURL(t *testing.T) { 1475 tt := []struct { 1476 in string 1477 outProtocol string 1478 outRegistry string 1479 outError error 1480 }{ 1481 {in: "https://my.registry.com", outProtocol: "https", outRegistry: "my.registry.com", outError: nil}, 1482 {in: "https://", outProtocol: "", outRegistry: "", outError: fmt.Errorf("Failed to split registry url 'https://'")}, 1483 {in: "my.registry.com", outProtocol: "", outRegistry: "", outError: fmt.Errorf("Failed to split registry url 'my.registry.com'")}, 1484 {in: "", outProtocol: "", outRegistry: "", outError: fmt.Errorf("Failed to split registry url ''")}, 1485 {in: "https://https://my.registry.com", outProtocol: "", outRegistry: "", outError: fmt.Errorf("Failed to split registry url 'https://https://my.registry.com'")}, 1486 } 1487 1488 for _, test := range tt { 1489 p, r, err := splitRegistryURL(test.in) 1490 assert.Equal(t, test.outProtocol, p, "Protocol value unexpected") 1491 assert.Equal(t, test.outRegistry, r, "Registry value unexpected") 1492 assert.Equal(t, test.outError, err, "Error value not as expected") 1493 } 1494 1495 } 1496 1497 func TestSplitImageName(t *testing.T) { 1498 tt := []struct { 1499 in string 1500 outImage string 1501 outTag string 1502 outError error 1503 }{ 1504 {in: "", outImage: "", outTag: "", outError: fmt.Errorf("Failed to split image name ''")}, 1505 {in: "path/to/image", outImage: "path/to/image", outTag: "", outError: nil}, 1506 {in: "path/to/image:tag", outImage: "path/to/image", outTag: "tag", outError: nil}, 1507 {in: "https://my.registry.com/path/to/image:tag", outImage: "", outTag: "", outError: fmt.Errorf("Failed to split image name 'https://my.registry.com/path/to/image:tag'")}, 1508 } 1509 for _, test := range tt { 1510 i, tag, err := splitFullImageName(test.in) 1511 assert.Equal(t, test.outImage, i, "Image value unexpected") 1512 assert.Equal(t, test.outTag, tag, "Tag value unexpected") 1513 assert.Equal(t, test.outError, err, "Error value not as expected") 1514 } 1515 }