github.com/koderover/helm@v2.17.0+incompatible/pkg/tiller/release_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 tiller 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 "k8s.io/helm/pkg/helm" 25 "k8s.io/helm/pkg/proto/hapi/chart" 26 "k8s.io/helm/pkg/proto/hapi/release" 27 "k8s.io/helm/pkg/proto/hapi/services" 28 "k8s.io/helm/pkg/version" 29 ) 30 31 func TestHasCRDHook(t *testing.T) { 32 tests := []struct { 33 hooks []*release.Hook 34 expect bool 35 }{ 36 { 37 hooks: []*release.Hook{ 38 {Events: []release.Hook_Event{release.Hook_PRE_DELETE}}, 39 }, 40 expect: false, 41 }, 42 { 43 hooks: []*release.Hook{ 44 {Events: []release.Hook_Event{release.Hook_CRD_INSTALL}}, 45 }, 46 expect: true, 47 }, 48 { 49 hooks: []*release.Hook{ 50 {Events: []release.Hook_Event{release.Hook_PRE_UPGRADE, release.Hook_CRD_INSTALL}}, 51 }, 52 expect: true, 53 }, 54 } 55 56 for i, tt := range tests { 57 if tt.expect != hasCRDHook(tt.hooks) { 58 t.Errorf("test %d: expected %t, got %t", i, tt.expect, !tt.expect) 59 } 60 } 61 } 62 63 func TestInstallRelease(t *testing.T) { 64 c := helm.NewContext() 65 rs := rsFixture() 66 67 req := installRequest() 68 res, err := rs.InstallRelease(c, req) 69 if err != nil { 70 t.Fatalf("Failed install: %s", err) 71 } 72 if res.Release.Name == "" { 73 t.Errorf("Expected release name.") 74 } 75 if res.Release.Namespace != "spaced" { 76 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 77 } 78 79 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 80 if err != nil { 81 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 82 } 83 84 t.Logf("rel: %v", rel) 85 86 if len(rel.Hooks) != 1 { 87 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 88 } 89 if rel.Hooks[0].Manifest != manifestWithHook { 90 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 91 } 92 93 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 94 t.Errorf("Expected event 0 is post install") 95 } 96 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 97 t.Errorf("Expected event 0 is pre-delete") 98 } 99 100 if len(res.Release.Manifest) == 0 { 101 t.Errorf("No manifest returned: %v", res.Release) 102 } 103 104 if len(rel.Manifest) == 0 { 105 t.Errorf("Expected manifest in %v", res) 106 } 107 108 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 109 t.Errorf("unexpected output: %s", rel.Manifest) 110 } 111 112 if rel.Info.Description != "Install complete" { 113 t.Errorf("unexpected description: %s", rel.Info.Description) 114 } 115 } 116 117 func TestInstallRelease_WithNotes(t *testing.T) { 118 c := helm.NewContext() 119 rs := rsFixture() 120 121 req := installRequest( 122 withChart(withNotes(notesText)), 123 ) 124 res, err := rs.InstallRelease(c, req) 125 if err != nil { 126 t.Fatalf("Failed install: %s", err) 127 } 128 if res.Release.Name == "" { 129 t.Errorf("Expected release name.") 130 } 131 if res.Release.Namespace != "spaced" { 132 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 133 } 134 135 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 136 if err != nil { 137 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 138 } 139 140 t.Logf("rel: %v", rel) 141 142 if len(rel.Hooks) != 1 { 143 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 144 } 145 if rel.Hooks[0].Manifest != manifestWithHook { 146 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 147 } 148 149 if rel.Info.Status.Notes != notesText { 150 t.Fatalf("Expected '%s', got '%s'", notesText, rel.Info.Status.Notes) 151 } 152 153 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 154 t.Errorf("Expected event 0 is post install") 155 } 156 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 157 t.Errorf("Expected event 0 is pre-delete") 158 } 159 160 if len(res.Release.Manifest) == 0 { 161 t.Errorf("No manifest returned: %v", res.Release) 162 } 163 164 if len(rel.Manifest) == 0 { 165 t.Errorf("Expected manifest in %v", res) 166 } 167 168 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 169 t.Errorf("unexpected output: %s", rel.Manifest) 170 } 171 172 if rel.Info.Description != "Install complete" { 173 t.Errorf("unexpected description: %s", rel.Info.Description) 174 } 175 } 176 177 func TestInstallRelease_WithNotesRendered(t *testing.T) { 178 c := helm.NewContext() 179 rs := rsFixture() 180 181 req := installRequest( 182 withChart(withNotes(notesText + " {{.Release.Name}}")), 183 ) 184 res, err := rs.InstallRelease(c, req) 185 if err != nil { 186 t.Fatalf("Failed install: %s", err) 187 } 188 if res.Release.Name == "" { 189 t.Errorf("Expected release name.") 190 } 191 if res.Release.Namespace != "spaced" { 192 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 193 } 194 195 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 196 if err != nil { 197 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 198 } 199 200 t.Logf("rel: %v", rel) 201 202 if len(rel.Hooks) != 1 { 203 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 204 } 205 if rel.Hooks[0].Manifest != manifestWithHook { 206 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 207 } 208 209 expectedNotes := fmt.Sprintf("%s %s", notesText, res.Release.Name) 210 if rel.Info.Status.Notes != expectedNotes { 211 t.Fatalf("Expected '%s', got '%s'", expectedNotes, rel.Info.Status.Notes) 212 } 213 214 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 215 t.Errorf("Expected event 0 is post install") 216 } 217 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 218 t.Errorf("Expected event 0 is pre-delete") 219 } 220 221 if len(res.Release.Manifest) == 0 { 222 t.Errorf("No manifest returned: %v", res.Release) 223 } 224 225 if len(rel.Manifest) == 0 { 226 t.Errorf("Expected manifest in %v", res) 227 } 228 229 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 230 t.Errorf("unexpected output: %s", rel.Manifest) 231 } 232 233 if rel.Info.Description != "Install complete" { 234 t.Errorf("unexpected description: %s", rel.Info.Description) 235 } 236 } 237 238 func TestInstallRelease_TillerVersion(t *testing.T) { 239 version.Version = "2.2.0" 240 c := helm.NewContext() 241 rs := rsFixture() 242 243 req := installRequest( 244 withChart(withTiller(">=2.2.0")), 245 ) 246 _, err := rs.InstallRelease(c, req) 247 if err != nil { 248 t.Fatalf("Expected valid range. Got %q", err) 249 } 250 } 251 252 func TestInstallRelease_WrongTillerVersion(t *testing.T) { 253 version.Version = "2.2.0" 254 c := helm.NewContext() 255 rs := rsFixture() 256 257 req := installRequest( 258 withChart(withTiller("<2.0.0")), 259 ) 260 _, err := rs.InstallRelease(c, req) 261 if err == nil { 262 t.Fatalf("Expected to fail because of wrong version") 263 } 264 265 expect := "Chart incompatible with Tiller" 266 if !strings.Contains(err.Error(), expect) { 267 t.Errorf("Expected %q to contain %q", err.Error(), expect) 268 } 269 } 270 271 func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) { 272 c := helm.NewContext() 273 rs := rsFixture() 274 275 req := installRequest(withChart( 276 withNotes(notesText), 277 withDependency(withNotes(notesText+" child")), 278 )) 279 res, err := rs.InstallRelease(c, req) 280 if err != nil { 281 t.Fatalf("Failed install: %s", err) 282 } 283 if res.Release.Name == "" { 284 t.Errorf("Expected release name.") 285 } 286 287 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 288 if err != nil { 289 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 290 } 291 292 t.Logf("rel: %v", rel) 293 294 if rel.Info.Status.Notes != notesText { 295 t.Fatalf("Expected '%s', got '%s'", notesText, rel.Info.Status.Notes) 296 } 297 298 if rel.Info.Description != "Install complete" { 299 t.Errorf("unexpected description: %s", rel.Info.Description) 300 } 301 } 302 303 func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) { 304 c := helm.NewContext() 305 rs := rsFixture() 306 307 req := installRequest(withSubNotes(), 308 withChart( 309 withNotes(notesText), 310 withDependency(withNotes(notesText+" child")), 311 )) 312 res, err := rs.InstallRelease(c, req) 313 if err != nil { 314 t.Fatalf("Failed install: %s", err) 315 } 316 if res.Release.Name == "" { 317 t.Errorf("Expected release name.") 318 } 319 320 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 321 if err != nil { 322 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 323 } 324 325 t.Logf("rel: %v", rel) 326 327 if !strings.Contains(rel.Info.Status.Notes, notesText) || !strings.Contains(rel.Info.Status.Notes, notesText+" child") { 328 t.Fatalf("Expected '%s', got '%s'", notesText+"\n"+notesText+" child", rel.Info.Status.Notes) 329 } 330 331 if rel.Info.Description != "Install complete" { 332 t.Errorf("unexpected description: %s", rel.Info.Description) 333 } 334 } 335 336 func TestInstallRelease_DryRun(t *testing.T) { 337 c := helm.NewContext() 338 rs := rsFixture() 339 340 req := installRequest(withDryRun(), 341 withChart(withSampleTemplates()), 342 ) 343 res, err := rs.InstallRelease(c, req) 344 if err != nil { 345 t.Errorf("Failed install: %s", err) 346 } 347 if res.Release.Name == "" { 348 t.Errorf("Expected release name.") 349 } 350 351 if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 352 t.Errorf("unexpected output: %s", res.Release.Manifest) 353 } 354 355 if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/goodbye\ngoodbye: world") { 356 t.Errorf("unexpected output: %s", res.Release.Manifest) 357 } 358 359 if !strings.Contains(res.Release.Manifest, "hello: Earth") { 360 t.Errorf("Should contain partial content. %s", res.Release.Manifest) 361 } 362 363 if strings.Contains(res.Release.Manifest, "hello: {{ template \"_planet\" . }}") { 364 t.Errorf("Should not contain partial templates itself. %s", res.Release.Manifest) 365 } 366 367 if strings.Contains(res.Release.Manifest, "empty") { 368 t.Errorf("Should not contain template data for an empty file. %s", res.Release.Manifest) 369 } 370 371 if _, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version); err == nil { 372 t.Errorf("Expected no stored release.") 373 } 374 375 if l := len(res.Release.Hooks); l != 1 { 376 t.Fatalf("Expected 1 hook, got %d", l) 377 } 378 379 if res.Release.Hooks[0].LastRun != nil { 380 t.Error("Expected hook to not be marked as run.") 381 } 382 383 if res.Release.Info.Description != "Dry run complete" { 384 t.Errorf("unexpected description: %s", res.Release.Info.Description) 385 } 386 } 387 388 func TestInstallRelease_NoHooks(t *testing.T) { 389 c := helm.NewContext() 390 rs := rsFixture() 391 rs.env.Releases.Create(releaseStub()) 392 393 req := installRequest(withDisabledHooks()) 394 res, err := rs.InstallRelease(c, req) 395 if err != nil { 396 t.Errorf("Failed install: %s", err) 397 } 398 399 if hl := res.Release.Hooks[0].LastRun; hl != nil { 400 t.Errorf("Expected that no hooks were run. Got %d", hl) 401 } 402 } 403 404 func TestInstallRelease_CRDInstallHook(t *testing.T) { 405 c := helm.NewContext() 406 rs := rsFixture() 407 rs.env.Releases.Create(releaseStub()) 408 409 req := installRequest() 410 req.Chart.Templates = append(req.Chart.Templates, &chart.Template{ 411 Name: "templates/crdhook", 412 Data: []byte(manifestWithCRDHook), 413 }) 414 415 res, err := rs.InstallRelease(c, req) 416 if err != nil { 417 t.Errorf("Failed install: %s", err) 418 } 419 420 // The new hook should have been pulled from the manifest. 421 if l := len(res.Release.Hooks); l != 2 { 422 t.Fatalf("expected 2 hooks, got %d", l) 423 } 424 425 expect := "Install complete" 426 if got := res.Release.Info.Description; got != expect { 427 t.Errorf("Expected Description to be %q, got %q", expect, got) 428 } 429 } 430 431 func TestInstallRelease_DryRunCRDInstallHook(t *testing.T) { 432 c := helm.NewContext() 433 rs := rsFixture() 434 rs.env.Releases.Create(releaseStub()) 435 436 req := installRequest(withDryRun()) 437 req.Chart.Templates = append(req.Chart.Templates, &chart.Template{ 438 Name: "templates/crdhook", 439 Data: []byte(manifestWithCRDHook), 440 }) 441 442 res, err := rs.InstallRelease(c, req) 443 if err != nil { 444 t.Errorf("Failed install: %s", err) 445 } 446 447 expect := "Validation skipped because CRDs are not installed" 448 if res.Release.Info.Description != expect { 449 t.Errorf("Expected Description %q, got %q", expect, res.Release.Info.Description) 450 } 451 } 452 453 func TestInstallRelease_FailedHooks(t *testing.T) { 454 c := helm.NewContext() 455 rs := rsFixture() 456 rs.env.Releases.Create(releaseStub()) 457 rs.env.KubeClient = newHookFailingKubeClient() 458 459 req := installRequest() 460 res, err := rs.InstallRelease(c, req) 461 if err == nil { 462 t.Error("Expected failed install") 463 } 464 465 if hl := res.Release.Info.Status.Code; hl != release.Status_FAILED { 466 t.Errorf("Expected FAILED release. Got %d", hl) 467 } 468 } 469 470 func TestInstallRelease_ReuseName(t *testing.T) { 471 c := helm.NewContext() 472 rs := rsFixture() 473 rel := releaseStub() 474 rel.Info.Status.Code = release.Status_DELETED 475 rs.env.Releases.Create(rel) 476 477 req := installRequest( 478 withReuseName(), 479 withName(rel.Name), 480 ) 481 res, err := rs.InstallRelease(c, req) 482 if err != nil { 483 t.Fatalf("Failed install: %s", err) 484 } 485 486 if res.Release.Name != rel.Name { 487 t.Errorf("expected %q, got %q", rel.Name, res.Release.Name) 488 } 489 490 getreq := &services.GetReleaseStatusRequest{Name: rel.Name, Version: 0} 491 getres, err := rs.GetReleaseStatus(c, getreq) 492 if err != nil { 493 t.Errorf("Failed to retrieve release: %s", err) 494 } 495 if getres.Info.Status.Code != release.Status_DEPLOYED { 496 t.Errorf("Release status is %q", getres.Info.Status.Code) 497 } 498 } 499 500 func TestInstallRelease_KubeVersion(t *testing.T) { 501 c := helm.NewContext() 502 rs := rsFixture() 503 504 req := installRequest( 505 withChart(withKube(">=0.0.0-0")), 506 ) 507 _, err := rs.InstallRelease(c, req) 508 if err != nil { 509 t.Fatalf("Expected valid range. Got %q", err) 510 } 511 } 512 513 func TestInstallRelease_WrongKubeVersion(t *testing.T) { 514 c := helm.NewContext() 515 rs := rsFixture() 516 517 req := installRequest( 518 withChart(withKube(">=5.0.0")), 519 ) 520 521 _, err := rs.InstallRelease(c, req) 522 if err == nil { 523 t.Fatalf("Expected to fail because of wrong version") 524 } 525 526 expect := "Chart requires kubernetesVersion" 527 if !strings.Contains(err.Error(), expect) { 528 t.Errorf("Expected %q to contain %q", err.Error(), expect) 529 } 530 } 531 532 func TestInstallRelease_Description(t *testing.T) { 533 c := helm.NewContext() 534 rs := rsFixture() 535 rs.env.Releases.Create(releaseStub()) 536 537 customDescription := "foo" 538 req := &services.InstallReleaseRequest{ 539 Chart: chartStub(), 540 Description: customDescription, 541 } 542 res, err := rs.InstallRelease(c, req) 543 if err != nil { 544 t.Errorf("Failed install: %s", err) 545 } 546 547 if desc := res.Release.Info.Description; desc != customDescription { 548 t.Errorf("Expected description %q. Got %q", customDescription, desc) 549 } 550 }