github.com/sdbaiguanghe/helm@v2.16.7+incompatible/cmd/helm/installer/install_test.go (about) 1 /* 2 Copyright The Helm Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package installer // import "k8s.io/helm/cmd/helm/installer" 18 19 import ( 20 "os" 21 "path/filepath" 22 "reflect" 23 "testing" 24 25 "github.com/ghodss/yaml" 26 appsv1 "k8s.io/api/apps/v1" 27 "k8s.io/api/core/v1" 28 apierrors "k8s.io/apimachinery/pkg/api/errors" 29 "k8s.io/apimachinery/pkg/runtime" 30 "k8s.io/client-go/kubernetes/fake" 31 testcore "k8s.io/client-go/testing" 32 33 "k8s.io/helm/pkg/chartutil" 34 "k8s.io/helm/pkg/version" 35 ) 36 37 func TestDeployment(t *testing.T) { 38 tests := []struct { 39 name string 40 image string 41 canary bool 42 expect string 43 imagePullPolicy v1.PullPolicy 44 }{ 45 {"default", "", false, "gcr.io/kubernetes-helm/tiller:" + version.Version, "IfNotPresent"}, 46 {"canary", "example.com/tiller", true, "gcr.io/kubernetes-helm/tiller:canary", "Always"}, 47 {"custom", "example.com/tiller:latest", false, "example.com/tiller:latest", "IfNotPresent"}, 48 } 49 50 for _, tt := range tests { 51 dep, err := Deployment(&Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary}) 52 if err != nil { 53 t.Fatalf("%s: error %q", tt.name, err) 54 } 55 56 // Unreleased versions of helm don't have a release image. See issue 3370 57 if tt.name == "default" && version.BuildMetadata == "unreleased" { 58 tt.expect = "gcr.io/kubernetes-helm/tiller:canary" 59 } 60 if got := dep.Spec.Template.Spec.Containers[0].Image; got != tt.expect { 61 t.Errorf("%s: expected image %q, got %q", tt.name, tt.expect, got) 62 } 63 64 if got := dep.Spec.Template.Spec.Containers[0].ImagePullPolicy; got != tt.imagePullPolicy { 65 t.Errorf("%s: expected imagePullPolicy %q, got %q", tt.name, tt.imagePullPolicy, got) 66 } 67 68 if got := dep.Spec.Template.Spec.Containers[0].Env[0].Value; got != v1.NamespaceDefault { 69 t.Errorf("%s: expected namespace %q, got %q", tt.name, v1.NamespaceDefault, got) 70 } 71 } 72 } 73 74 func TestDeploymentForServiceAccount(t *testing.T) { 75 tests := []struct { 76 name string 77 image string 78 canary bool 79 expect string 80 imagePullPolicy v1.PullPolicy 81 serviceAccount string 82 }{ 83 {"withSA", "", false, "gcr.io/kubernetes-helm/tiller:latest", "IfNotPresent", "service-account"}, 84 {"withoutSA", "", false, "gcr.io/kubernetes-helm/tiller:latest", "IfNotPresent", ""}, 85 } 86 for _, tt := range tests { 87 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary, ServiceAccount: tt.serviceAccount} 88 d, err := Deployment(opts) 89 if err != nil { 90 t.Fatalf("%s: error %q", tt.name, err) 91 } 92 93 if got := d.Spec.Template.Spec.ServiceAccountName; got != tt.serviceAccount { 94 t.Errorf("%s: expected service account value %q, got %q", tt.name, tt.serviceAccount, got) 95 } 96 if got := *d.Spec.Template.Spec.AutomountServiceAccountToken; got != false { 97 t.Errorf("%s: expected AutomountServiceAccountToken = %t, got %t", tt.name, false, got) 98 } 99 100 opts.AutoMountServiceAccountToken = true 101 d, err = Deployment(opts) 102 if err != nil { 103 t.Fatalf("%s: error %q", tt.name, err) 104 } 105 if got := *d.Spec.Template.Spec.AutomountServiceAccountToken; got != true { 106 t.Errorf("%s: expected AutomountServiceAccountToken = %t, got %t", tt.name, true, got) 107 } 108 } 109 } 110 111 func TestDeployment_WithTLS(t *testing.T) { 112 tests := []struct { 113 opts Options 114 name string 115 enable string 116 verify string 117 }{ 118 { 119 Options{Namespace: v1.NamespaceDefault, EnableTLS: true, VerifyTLS: true}, 120 "tls enable (true), tls verify (true)", 121 "1", 122 "1", 123 }, 124 { 125 Options{Namespace: v1.NamespaceDefault, EnableTLS: true, VerifyTLS: false}, 126 "tls enable (true), tls verify (false)", 127 "1", 128 "", 129 }, 130 { 131 Options{Namespace: v1.NamespaceDefault, EnableTLS: false, VerifyTLS: true}, 132 "tls enable (false), tls verify (true)", 133 "1", 134 "1", 135 }, 136 } 137 for _, tt := range tests { 138 d, err := Deployment(&tt.opts) 139 if err != nil { 140 t.Fatalf("%s: error %q", tt.name, err) 141 } 142 143 // verify environment variable in deployment reflect the use of tls being enabled. 144 if got := d.Spec.Template.Spec.Containers[0].Env[2].Value; got != tt.verify { 145 t.Errorf("%s: expected tls verify env value %q, got %q", tt.name, tt.verify, got) 146 } 147 if got := d.Spec.Template.Spec.Containers[0].Env[3].Value; got != tt.enable { 148 t.Errorf("%s: expected tls enable env value %q, got %q", tt.name, tt.enable, got) 149 } 150 } 151 } 152 153 func TestServiceManifest(t *testing.T) { 154 svc := Service(v1.NamespaceDefault) 155 156 if got := svc.ObjectMeta.Namespace; got != v1.NamespaceDefault { 157 t.Errorf("expected namespace %s, got %s", v1.NamespaceDefault, got) 158 } 159 } 160 161 func TestSecretManifest(t *testing.T) { 162 obj, err := Secret(&Options{ 163 VerifyTLS: true, 164 EnableTLS: true, 165 Namespace: v1.NamespaceDefault, 166 TLSKeyFile: tlsTestFile(t, "key.pem"), 167 TLSCertFile: tlsTestFile(t, "crt.pem"), 168 TLSCaCertFile: tlsTestFile(t, "ca.pem"), 169 }) 170 171 if err != nil { 172 t.Fatalf("error %q", err) 173 } 174 175 if got := obj.ObjectMeta.Namespace; got != v1.NamespaceDefault { 176 t.Errorf("expected namespace %s, got %s", v1.NamespaceDefault, got) 177 } 178 if _, ok := obj.Data["tls.key"]; !ok { 179 t.Errorf("missing 'tls.key' in generated secret object") 180 } 181 if _, ok := obj.Data["tls.crt"]; !ok { 182 t.Errorf("missing 'tls.crt' in generated secret object") 183 } 184 if _, ok := obj.Data["ca.crt"]; !ok { 185 t.Errorf("missing 'ca.crt' in generated secret object") 186 } 187 } 188 189 func TestInstall(t *testing.T) { 190 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 191 192 fc := &fake.Clientset{} 193 fc.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 194 obj := action.(testcore.CreateAction).GetObject().(*appsv1.Deployment) 195 l := obj.GetLabels() 196 if reflect.DeepEqual(l, map[string]string{"app": "helm"}) { 197 t.Errorf("expected labels = '', got '%s'", l) 198 } 199 i := obj.Spec.Template.Spec.Containers[0].Image 200 if i != image { 201 t.Errorf("expected image = '%s', got '%s'", image, i) 202 } 203 ports := len(obj.Spec.Template.Spec.Containers[0].Ports) 204 if ports != 2 { 205 t.Errorf("expected ports = 2, got '%d'", ports) 206 } 207 replicas := obj.Spec.Replicas 208 if int(*replicas) != 1 { 209 t.Errorf("expected replicas = 1, got '%d'", replicas) 210 } 211 return true, obj, nil 212 }) 213 fc.AddReactor("create", "services", func(action testcore.Action) (bool, runtime.Object, error) { 214 obj := action.(testcore.CreateAction).GetObject().(*v1.Service) 215 l := obj.GetLabels() 216 if reflect.DeepEqual(l, map[string]string{"app": "helm"}) { 217 t.Errorf("expected labels = '', got '%s'", l) 218 } 219 n := obj.ObjectMeta.Namespace 220 if n != v1.NamespaceDefault { 221 t.Errorf("expected namespace = '%s', got '%s'", v1.NamespaceDefault, n) 222 } 223 return true, obj, nil 224 }) 225 226 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image} 227 if err := Install(fc, opts); err != nil { 228 t.Errorf("unexpected error: %#+v", err) 229 } 230 231 if actions := fc.Actions(); len(actions) != 2 { 232 t.Errorf("unexpected actions: %v, expected 2 actions got %d", actions, len(actions)) 233 } 234 } 235 236 func TestInstallHA(t *testing.T) { 237 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 238 239 fc := &fake.Clientset{} 240 fc.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 241 obj := action.(testcore.CreateAction).GetObject().(*appsv1.Deployment) 242 replicas := obj.Spec.Replicas 243 if int(*replicas) != 2 { 244 t.Errorf("expected replicas = 2, got '%d'", replicas) 245 } 246 return true, obj, nil 247 }) 248 249 opts := &Options{ 250 Namespace: v1.NamespaceDefault, 251 ImageSpec: image, 252 Replicas: 2, 253 } 254 if err := Install(fc, opts); err != nil { 255 t.Errorf("unexpected error: %#+v", err) 256 } 257 } 258 259 func TestInstall_WithTLS(t *testing.T) { 260 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 261 name := "tiller-secret" 262 263 fc := &fake.Clientset{} 264 fc.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 265 obj := action.(testcore.CreateAction).GetObject().(*appsv1.Deployment) 266 l := obj.GetLabels() 267 if reflect.DeepEqual(l, map[string]string{"app": "helm"}) { 268 t.Errorf("expected labels = '', got '%s'", l) 269 } 270 i := obj.Spec.Template.Spec.Containers[0].Image 271 if i != image { 272 t.Errorf("expected image = '%s', got '%s'", image, i) 273 } 274 return true, obj, nil 275 }) 276 fc.AddReactor("create", "services", func(action testcore.Action) (bool, runtime.Object, error) { 277 obj := action.(testcore.CreateAction).GetObject().(*v1.Service) 278 l := obj.GetLabels() 279 if reflect.DeepEqual(l, map[string]string{"app": "helm"}) { 280 t.Errorf("expected labels = '', got '%s'", l) 281 } 282 n := obj.ObjectMeta.Namespace 283 if n != v1.NamespaceDefault { 284 t.Errorf("expected namespace = '%s', got '%s'", v1.NamespaceDefault, n) 285 } 286 return true, obj, nil 287 }) 288 fc.AddReactor("create", "secrets", func(action testcore.Action) (bool, runtime.Object, error) { 289 obj := action.(testcore.CreateAction).GetObject().(*v1.Secret) 290 if l := obj.GetLabels(); reflect.DeepEqual(l, map[string]string{"app": "helm"}) { 291 t.Errorf("expected labels = '', got '%s'", l) 292 } 293 if n := obj.ObjectMeta.Namespace; n != v1.NamespaceDefault { 294 t.Errorf("expected namespace = '%s', got '%s'", v1.NamespaceDefault, n) 295 } 296 if s := obj.ObjectMeta.Name; s != name { 297 t.Errorf("expected name = '%s', got '%s'", name, s) 298 } 299 if _, ok := obj.Data["tls.key"]; !ok { 300 t.Errorf("missing 'tls.key' in generated secret object") 301 } 302 if _, ok := obj.Data["tls.crt"]; !ok { 303 t.Errorf("missing 'tls.crt' in generated secret object") 304 } 305 if _, ok := obj.Data["ca.crt"]; !ok { 306 t.Errorf("missing 'ca.crt' in generated secret object") 307 } 308 return true, obj, nil 309 }) 310 311 opts := &Options{ 312 Namespace: v1.NamespaceDefault, 313 ImageSpec: image, 314 EnableTLS: true, 315 VerifyTLS: true, 316 TLSKeyFile: tlsTestFile(t, "key.pem"), 317 TLSCertFile: tlsTestFile(t, "crt.pem"), 318 TLSCaCertFile: tlsTestFile(t, "ca.pem"), 319 } 320 321 if err := Install(fc, opts); err != nil { 322 t.Errorf("unexpected error: %#+v", err) 323 } 324 325 if actions := fc.Actions(); len(actions) != 3 { 326 t.Errorf("unexpected actions: %v, expected 3 actions got %d", actions, len(actions)) 327 } 328 } 329 330 func TestInstall_canary(t *testing.T) { 331 fc := &fake.Clientset{} 332 fc.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 333 obj := action.(testcore.CreateAction).GetObject().(*appsv1.Deployment) 334 i := obj.Spec.Template.Spec.Containers[0].Image 335 if i != "gcr.io/kubernetes-helm/tiller:canary" { 336 t.Errorf("expected canary image, got '%s'", i) 337 } 338 return true, obj, nil 339 }) 340 fc.AddReactor("create", "services", func(action testcore.Action) (bool, runtime.Object, error) { 341 obj := action.(testcore.CreateAction).GetObject().(*v1.Service) 342 return true, obj, nil 343 }) 344 345 opts := &Options{Namespace: v1.NamespaceDefault, UseCanary: true} 346 if err := Install(fc, opts); err != nil { 347 t.Errorf("unexpected error: %#+v", err) 348 } 349 350 if actions := fc.Actions(); len(actions) != 2 { 351 t.Errorf("unexpected actions: %v, expected 2 actions got %d", actions, len(actions)) 352 } 353 } 354 355 func TestUpgrade(t *testing.T) { 356 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 357 serviceAccount := "newServiceAccount" 358 existingDeployment, _ := generateDeployment(&Options{ 359 Namespace: v1.NamespaceDefault, 360 ImageSpec: "imageToReplace:v1.0.0", 361 ServiceAccount: "serviceAccountToReplace", 362 UseCanary: false, 363 }) 364 existingService := generateService(v1.NamespaceDefault) 365 366 fc := &fake.Clientset{} 367 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 368 return true, existingDeployment, nil 369 }) 370 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 371 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 372 i := obj.Spec.Template.Spec.Containers[0].Image 373 if i != image { 374 t.Errorf("expected image = '%s', got '%s'", image, i) 375 } 376 sa := obj.Spec.Template.Spec.ServiceAccountName 377 if sa != serviceAccount { 378 t.Errorf("expected serviceAccountName = '%s', got '%s'", serviceAccount, sa) 379 } 380 return true, obj, nil 381 }) 382 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 383 return true, existingService, nil 384 }) 385 386 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image, ServiceAccount: serviceAccount} 387 if err := Upgrade(fc, opts); err != nil { 388 t.Errorf("unexpected error: %#+v", err) 389 } 390 391 if actions := fc.Actions(); len(actions) != 3 { 392 t.Errorf("unexpected actions: %v, expected 3 actions got %d", actions, len(actions)) 393 } 394 } 395 396 func TestUpgrade_serviceNotFound(t *testing.T) { 397 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 398 399 existingDeployment, _ := generateDeployment(&Options{ 400 Namespace: v1.NamespaceDefault, 401 ImageSpec: "imageToReplace", 402 UseCanary: false, 403 }) 404 405 fc := &fake.Clientset{} 406 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 407 return true, existingDeployment, nil 408 }) 409 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 410 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 411 i := obj.Spec.Template.Spec.Containers[0].Image 412 if i != image { 413 t.Errorf("expected image = '%s', got '%s'", image, i) 414 } 415 return true, obj, nil 416 }) 417 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 418 return true, nil, apierrors.NewNotFound(v1.Resource("services"), "1") 419 }) 420 fc.AddReactor("create", "services", func(action testcore.Action) (bool, runtime.Object, error) { 421 obj := action.(testcore.CreateAction).GetObject().(*v1.Service) 422 n := obj.ObjectMeta.Namespace 423 if n != v1.NamespaceDefault { 424 t.Errorf("expected namespace = '%s', got '%s'", v1.NamespaceDefault, n) 425 } 426 return true, obj, nil 427 }) 428 429 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image} 430 if err := Upgrade(fc, opts); err != nil { 431 t.Errorf("unexpected error: %#+v", err) 432 } 433 434 if actions := fc.Actions(); len(actions) != 4 { 435 t.Errorf("unexpected actions: %v, expected 4 actions got %d", actions, len(actions)) 436 } 437 } 438 439 func TestUgrade_newerVersion(t *testing.T) { 440 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 441 serviceAccount := "newServiceAccount" 442 existingDeployment, _ := generateDeployment(&Options{ 443 Namespace: v1.NamespaceDefault, 444 ImageSpec: "imageToReplace:v100.5.0", 445 ServiceAccount: "serviceAccountToReplace", 446 UseCanary: false, 447 }) 448 existingService := generateService(v1.NamespaceDefault) 449 450 fc := &fake.Clientset{} 451 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 452 return true, existingDeployment, nil 453 }) 454 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 455 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 456 i := obj.Spec.Template.Spec.Containers[0].Image 457 if i != image { 458 t.Errorf("expected image = '%s', got '%s'", image, i) 459 } 460 sa := obj.Spec.Template.Spec.ServiceAccountName 461 if sa != serviceAccount { 462 t.Errorf("expected serviceAccountName = '%s', got '%s'", serviceAccount, sa) 463 } 464 return true, obj, nil 465 }) 466 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 467 return true, existingService, nil 468 }) 469 470 opts := &Options{ 471 Namespace: v1.NamespaceDefault, 472 ImageSpec: image, 473 ServiceAccount: serviceAccount, 474 ForceUpgrade: false, 475 } 476 if err := Upgrade(fc, opts); err == nil { 477 t.Errorf("Expected error because the deployed version is newer") 478 } 479 480 if actions := fc.Actions(); len(actions) != 1 { 481 t.Errorf("unexpected actions: %v, expected 1 action got %d", actions, len(actions)) 482 } 483 484 opts = &Options{ 485 Namespace: v1.NamespaceDefault, 486 ImageSpec: image, 487 ServiceAccount: serviceAccount, 488 ForceUpgrade: true, 489 } 490 if err := Upgrade(fc, opts); err != nil { 491 t.Errorf("unexpected error: %#+v", err) 492 } 493 494 if actions := fc.Actions(); len(actions) != 4 { 495 t.Errorf("unexpected actions: %v, expected 4 action got %d", actions, len(actions)) 496 } 497 } 498 499 func TestUpgrade_identical(t *testing.T) { 500 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 501 serviceAccount := "newServiceAccount" 502 existingDeployment, _ := generateDeployment(&Options{ 503 Namespace: v1.NamespaceDefault, 504 ImageSpec: "imageToReplace:v2.0.0", 505 ServiceAccount: "serviceAccountToReplace", 506 UseCanary: false, 507 }) 508 existingService := generateService(v1.NamespaceDefault) 509 510 fc := &fake.Clientset{} 511 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 512 return true, existingDeployment, nil 513 }) 514 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 515 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 516 i := obj.Spec.Template.Spec.Containers[0].Image 517 if i != image { 518 t.Errorf("expected image = '%s', got '%s'", image, i) 519 } 520 sa := obj.Spec.Template.Spec.ServiceAccountName 521 if sa != serviceAccount { 522 t.Errorf("expected serviceAccountName = '%s', got '%s'", serviceAccount, sa) 523 } 524 return true, obj, nil 525 }) 526 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 527 return true, existingService, nil 528 }) 529 530 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image, ServiceAccount: serviceAccount} 531 if err := Upgrade(fc, opts); err != nil { 532 t.Errorf("unexpected error: %#+v", err) 533 } 534 535 if actions := fc.Actions(); len(actions) != 3 { 536 t.Errorf("unexpected actions: %v, expected 3 actions got %d", actions, len(actions)) 537 } 538 } 539 540 func TestUpgrade_canaryClient(t *testing.T) { 541 image := "gcr.io/kubernetes-helm/tiller:canary" 542 serviceAccount := "newServiceAccount" 543 existingDeployment, _ := generateDeployment(&Options{ 544 Namespace: v1.NamespaceDefault, 545 ImageSpec: "imageToReplace:v1.0.0", 546 ServiceAccount: "serviceAccountToReplace", 547 UseCanary: false, 548 }) 549 existingService := generateService(v1.NamespaceDefault) 550 551 fc := &fake.Clientset{} 552 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 553 return true, existingDeployment, nil 554 }) 555 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 556 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 557 i := obj.Spec.Template.Spec.Containers[0].Image 558 if i != image { 559 t.Errorf("expected image = '%s', got '%s'", image, i) 560 } 561 sa := obj.Spec.Template.Spec.ServiceAccountName 562 if sa != serviceAccount { 563 t.Errorf("expected serviceAccountName = '%s', got '%s'", serviceAccount, sa) 564 } 565 return true, obj, nil 566 }) 567 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 568 return true, existingService, nil 569 }) 570 571 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image, ServiceAccount: serviceAccount} 572 if err := Upgrade(fc, opts); err != nil { 573 t.Errorf("unexpected error: %#+v", err) 574 } 575 576 if actions := fc.Actions(); len(actions) != 3 { 577 t.Errorf("unexpected actions: %v, expected 3 actions got %d", actions, len(actions)) 578 } 579 } 580 581 func TestUpgrade_canaryServer(t *testing.T) { 582 image := "gcr.io/kubernetes-helm/tiller:v2.0.0" 583 serviceAccount := "newServiceAccount" 584 existingDeployment, _ := generateDeployment(&Options{ 585 Namespace: v1.NamespaceDefault, 586 ImageSpec: "imageToReplace:canary", 587 ServiceAccount: "serviceAccountToReplace", 588 UseCanary: false, 589 }) 590 existingService := generateService(v1.NamespaceDefault) 591 592 fc := &fake.Clientset{} 593 fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 594 return true, existingDeployment, nil 595 }) 596 fc.AddReactor("update", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { 597 obj := action.(testcore.UpdateAction).GetObject().(*appsv1.Deployment) 598 i := obj.Spec.Template.Spec.Containers[0].Image 599 if i != image { 600 t.Errorf("expected image = '%s', got '%s'", image, i) 601 } 602 sa := obj.Spec.Template.Spec.ServiceAccountName 603 if sa != serviceAccount { 604 t.Errorf("expected serviceAccountName = '%s', got '%s'", serviceAccount, sa) 605 } 606 return true, obj, nil 607 }) 608 fc.AddReactor("get", "services", func(action testcore.Action) (bool, runtime.Object, error) { 609 return true, existingService, nil 610 }) 611 612 opts := &Options{Namespace: v1.NamespaceDefault, ImageSpec: image, ServiceAccount: serviceAccount} 613 if err := Upgrade(fc, opts); err != nil { 614 t.Errorf("unexpected error: %#+v", err) 615 } 616 617 if actions := fc.Actions(); len(actions) != 3 { 618 t.Errorf("unexpected actions: %v, expected 3 actions got %d", actions, len(actions)) 619 } 620 } 621 622 func tlsTestFile(t *testing.T, path string) string { 623 const tlsTestDir = "../../../testdata" 624 path = filepath.Join(tlsTestDir, path) 625 if _, err := os.Stat(path); os.IsNotExist(err) { 626 t.Fatalf("tls test file %s does not exist", path) 627 } 628 return path 629 } 630 631 func TestDeployment_WithNodeSelectors(t *testing.T) { 632 tests := []struct { 633 opts Options 634 name string 635 expect map[string]interface{} 636 }{ 637 { 638 Options{Namespace: v1.NamespaceDefault, NodeSelectors: "app=tiller"}, 639 "nodeSelector app=tiller", 640 map[string]interface{}{"app": "tiller"}, 641 }, 642 { 643 Options{Namespace: v1.NamespaceDefault, NodeSelectors: "app=tiller,helm=rocks"}, 644 "nodeSelector app=tiller, helm=rocks", 645 map[string]interface{}{"app": "tiller", "helm": "rocks"}, 646 }, 647 // note: nodeSelector key and value are strings 648 { 649 Options{Namespace: v1.NamespaceDefault, NodeSelectors: "app=tiller,minCoolness=1"}, 650 "nodeSelector app=tiller, helm=rocks", 651 map[string]interface{}{"app": "tiller", "minCoolness": "1"}, 652 }, 653 } 654 for _, tt := range tests { 655 d, err := Deployment(&tt.opts) 656 if err != nil { 657 t.Fatalf("%s: error %q", tt.name, err) 658 } 659 660 // Verify that environment variables in Deployment reflect the use of TLS being enabled. 661 got := d.Spec.Template.Spec.NodeSelector 662 for k, v := range tt.expect { 663 if got[k] != v { 664 t.Errorf("%s: expected nodeSelector value %q, got %q", tt.name, tt.expect, got) 665 } 666 } 667 } 668 } 669 670 func TestDeployment_WithSetValues(t *testing.T) { 671 tests := []struct { 672 opts Options 673 name string 674 expectPath string 675 expect interface{} 676 }{ 677 { 678 Options{Namespace: v1.NamespaceDefault, Values: []string{"spec.template.spec.nodeselector.app=tiller"}}, 679 "setValues spec.template.spec.nodeSelector.app=tiller", 680 "spec.template.spec.nodeSelector.app", 681 "tiller", 682 }, 683 { 684 Options{Namespace: v1.NamespaceDefault, Values: []string{"spec.replicas=2"}}, 685 "setValues spec.replicas=2", 686 "spec.replicas", 687 2, 688 }, 689 { 690 Options{Namespace: v1.NamespaceDefault, Values: []string{"spec.template.spec.activedeadlineseconds=120"}}, 691 "setValues spec.template.spec.activedeadlineseconds=120", 692 "spec.template.spec.activeDeadlineSeconds", 693 120, 694 }, 695 } 696 for _, tt := range tests { 697 d, err := Deployment(&tt.opts) 698 if err != nil { 699 t.Fatalf("%s: error %q", tt.name, err) 700 } 701 702 o, err := yaml.Marshal(d) 703 if err != nil { 704 t.Errorf("Error marshaling Deployment: %s", err) 705 } 706 707 values, err := chartutil.ReadValues(o) 708 if err != nil { 709 t.Errorf("Error converting Deployment manifest to Values: %s", err) 710 } 711 // path value 712 pv, err := values.PathValue(tt.expectPath) 713 if err != nil { 714 t.Errorf("Error retrieving path value from Deployment Values: %s", err) 715 } 716 717 // convert our expected value to match the result type for comparison 718 ev := tt.expect 719 switch pvt := pv.(type) { 720 case float64: 721 floatType := reflect.TypeOf(float64(0)) 722 v := reflect.ValueOf(ev) 723 v = reflect.Indirect(v) 724 if !v.Type().ConvertibleTo(floatType) { 725 t.Fatalf("Error converting expected value %v to float64", v.Type()) 726 } 727 fv := v.Convert(floatType) 728 if fv.Float() != pvt { 729 t.Errorf("%s: expected value %q, got %q", tt.name, tt.expect, pv) 730 } 731 default: 732 if pv != tt.expect { 733 t.Errorf("%s: expected value %q, got %q", tt.name, tt.expect, pv) 734 } 735 } 736 } 737 }