github.com/darkowlzz/helm@v2.5.1-0.20171213183701-6707fe0468d4+incompatible/pkg/tiller/release_install_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 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 TestInstallRelease(t *testing.T) { 32 c := helm.NewContext() 33 rs := rsFixture() 34 35 // TODO: Refactor this into a mock. 36 req := &services.InstallReleaseRequest{ 37 Namespace: "spaced", 38 Chart: &chart.Chart{ 39 Metadata: &chart.Metadata{Name: "hello"}, 40 Templates: []*chart.Template{ 41 {Name: "templates/hello", Data: []byte("hello: world")}, 42 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 43 }, 44 }, 45 } 46 res, err := rs.InstallRelease(c, req) 47 if err != nil { 48 t.Fatalf("Failed install: %s", err) 49 } 50 if res.Release.Name == "" { 51 t.Errorf("Expected release name.") 52 } 53 if res.Release.Namespace != "spaced" { 54 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 55 } 56 57 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 58 if err != nil { 59 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 60 } 61 62 t.Logf("rel: %v", rel) 63 64 if len(rel.Hooks) != 1 { 65 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 66 } 67 if rel.Hooks[0].Manifest != manifestWithHook { 68 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 69 } 70 71 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 72 t.Errorf("Expected event 0 is post install") 73 } 74 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 75 t.Errorf("Expected event 0 is pre-delete") 76 } 77 78 if len(res.Release.Manifest) == 0 { 79 t.Errorf("No manifest returned: %v", res.Release) 80 } 81 82 if len(rel.Manifest) == 0 { 83 t.Errorf("Expected manifest in %v", res) 84 } 85 86 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 87 t.Errorf("unexpected output: %s", rel.Manifest) 88 } 89 90 if rel.Info.Description != "Install complete" { 91 t.Errorf("unexpected description: %s", rel.Info.Description) 92 } 93 } 94 95 func TestInstallRelease_WithNotes(t *testing.T) { 96 c := helm.NewContext() 97 rs := rsFixture() 98 99 // TODO: Refactor this into a mock. 100 req := &services.InstallReleaseRequest{ 101 Namespace: "spaced", 102 Chart: &chart.Chart{ 103 Metadata: &chart.Metadata{Name: "hello"}, 104 Templates: []*chart.Template{ 105 {Name: "templates/hello", Data: []byte("hello: world")}, 106 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 107 {Name: "templates/NOTES.txt", Data: []byte(notesText)}, 108 }, 109 }, 110 } 111 res, err := rs.InstallRelease(c, req) 112 if err != nil { 113 t.Fatalf("Failed install: %s", err) 114 } 115 if res.Release.Name == "" { 116 t.Errorf("Expected release name.") 117 } 118 if res.Release.Namespace != "spaced" { 119 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 120 } 121 122 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 123 if err != nil { 124 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 125 } 126 127 t.Logf("rel: %v", rel) 128 129 if len(rel.Hooks) != 1 { 130 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 131 } 132 if rel.Hooks[0].Manifest != manifestWithHook { 133 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 134 } 135 136 if rel.Info.Status.Notes != notesText { 137 t.Fatalf("Expected '%s', got '%s'", notesText, rel.Info.Status.Notes) 138 } 139 140 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 141 t.Errorf("Expected event 0 is post install") 142 } 143 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 144 t.Errorf("Expected event 0 is pre-delete") 145 } 146 147 if len(res.Release.Manifest) == 0 { 148 t.Errorf("No manifest returned: %v", res.Release) 149 } 150 151 if len(rel.Manifest) == 0 { 152 t.Errorf("Expected manifest in %v", res) 153 } 154 155 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 156 t.Errorf("unexpected output: %s", rel.Manifest) 157 } 158 159 if rel.Info.Description != "Install complete" { 160 t.Errorf("unexpected description: %s", rel.Info.Description) 161 } 162 } 163 164 func TestInstallRelease_WithNotesRendered(t *testing.T) { 165 c := helm.NewContext() 166 rs := rsFixture() 167 168 // TODO: Refactor this into a mock. 169 req := &services.InstallReleaseRequest{ 170 Namespace: "spaced", 171 Chart: &chart.Chart{ 172 Metadata: &chart.Metadata{Name: "hello"}, 173 Templates: []*chart.Template{ 174 {Name: "templates/hello", Data: []byte("hello: world")}, 175 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 176 {Name: "templates/NOTES.txt", Data: []byte(notesText + " {{.Release.Name}}")}, 177 }, 178 }, 179 } 180 res, err := rs.InstallRelease(c, req) 181 if err != nil { 182 t.Fatalf("Failed install: %s", err) 183 } 184 if res.Release.Name == "" { 185 t.Errorf("Expected release name.") 186 } 187 if res.Release.Namespace != "spaced" { 188 t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) 189 } 190 191 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 192 if err != nil { 193 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 194 } 195 196 t.Logf("rel: %v", rel) 197 198 if len(rel.Hooks) != 1 { 199 t.Fatalf("Expected 1 hook, got %d", len(rel.Hooks)) 200 } 201 if rel.Hooks[0].Manifest != manifestWithHook { 202 t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) 203 } 204 205 expectedNotes := fmt.Sprintf("%s %s", notesText, res.Release.Name) 206 if rel.Info.Status.Notes != expectedNotes { 207 t.Fatalf("Expected '%s', got '%s'", expectedNotes, rel.Info.Status.Notes) 208 } 209 210 if rel.Hooks[0].Events[0] != release.Hook_POST_INSTALL { 211 t.Errorf("Expected event 0 is post install") 212 } 213 if rel.Hooks[0].Events[1] != release.Hook_PRE_DELETE { 214 t.Errorf("Expected event 0 is pre-delete") 215 } 216 217 if len(res.Release.Manifest) == 0 { 218 t.Errorf("No manifest returned: %v", res.Release) 219 } 220 221 if len(rel.Manifest) == 0 { 222 t.Errorf("Expected manifest in %v", res) 223 } 224 225 if !strings.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 226 t.Errorf("unexpected output: %s", rel.Manifest) 227 } 228 229 if rel.Info.Description != "Install complete" { 230 t.Errorf("unexpected description: %s", rel.Info.Description) 231 } 232 } 233 234 func TestInstallRelease_TillerVersion(t *testing.T) { 235 version.Version = "2.2.0" 236 c := helm.NewContext() 237 rs := rsFixture() 238 239 // TODO: Refactor this into a mock. 240 req := &services.InstallReleaseRequest{ 241 Namespace: "spaced", 242 Chart: &chart.Chart{ 243 Metadata: &chart.Metadata{Name: "hello", TillerVersion: ">=2.2.0"}, 244 Templates: []*chart.Template{ 245 {Name: "templates/hello", Data: []byte("hello: world")}, 246 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 247 }, 248 }, 249 } 250 _, err := rs.InstallRelease(c, req) 251 if err != nil { 252 t.Fatalf("Expected valid range. Got %q", err) 253 } 254 } 255 256 func TestInstallRelease_WrongTillerVersion(t *testing.T) { 257 version.Version = "2.2.0" 258 c := helm.NewContext() 259 rs := rsFixture() 260 261 // TODO: Refactor this into a mock. 262 req := &services.InstallReleaseRequest{ 263 Namespace: "spaced", 264 Chart: &chart.Chart{ 265 Metadata: &chart.Metadata{Name: "hello", TillerVersion: "<2.0.0"}, 266 Templates: []*chart.Template{ 267 {Name: "templates/hello", Data: []byte("hello: world")}, 268 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 269 }, 270 }, 271 } 272 _, err := rs.InstallRelease(c, req) 273 if err == nil { 274 t.Fatalf("Expected to fail because of wrong version") 275 } 276 277 expect := "Chart incompatible with Tiller" 278 if !strings.Contains(err.Error(), expect) { 279 t.Errorf("Expected %q to contain %q", err.Error(), expect) 280 } 281 } 282 283 func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) { 284 c := helm.NewContext() 285 rs := rsFixture() 286 287 // TODO: Refactor this into a mock. 288 req := &services.InstallReleaseRequest{ 289 Namespace: "spaced", 290 Chart: &chart.Chart{ 291 Metadata: &chart.Metadata{Name: "hello"}, 292 Templates: []*chart.Template{ 293 {Name: "templates/hello", Data: []byte("hello: world")}, 294 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 295 {Name: "templates/NOTES.txt", Data: []byte(notesText)}, 296 }, 297 Dependencies: []*chart.Chart{ 298 { 299 Metadata: &chart.Metadata{Name: "hello"}, 300 Templates: []*chart.Template{ 301 {Name: "templates/hello", Data: []byte("hello: world")}, 302 {Name: "templates/hooks", Data: []byte(manifestWithHook)}, 303 {Name: "templates/NOTES.txt", Data: []byte(notesText + " child")}, 304 }, 305 }, 306 }, 307 }, 308 } 309 310 res, err := rs.InstallRelease(c, req) 311 if err != nil { 312 t.Fatalf("Failed install: %s", err) 313 } 314 if res.Release.Name == "" { 315 t.Errorf("Expected release name.") 316 } 317 318 rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) 319 if err != nil { 320 t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) 321 } 322 323 t.Logf("rel: %v", rel) 324 325 if rel.Info.Status.Notes != notesText { 326 t.Fatalf("Expected '%s', got '%s'", notesText, rel.Info.Status.Notes) 327 } 328 329 if rel.Info.Description != "Install complete" { 330 t.Errorf("unexpected description: %s", rel.Info.Description) 331 } 332 } 333 334 func TestInstallRelease_DryRun(t *testing.T) { 335 c := helm.NewContext() 336 rs := rsFixture() 337 338 req := &services.InstallReleaseRequest{ 339 Chart: chartStub(), 340 DryRun: true, 341 } 342 res, err := rs.InstallRelease(c, req) 343 if err != nil { 344 t.Errorf("Failed install: %s", err) 345 } 346 if res.Release.Name == "" { 347 t.Errorf("Expected release name.") 348 } 349 350 if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { 351 t.Errorf("unexpected output: %s", res.Release.Manifest) 352 } 353 354 if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/goodbye\ngoodbye: world") { 355 t.Errorf("unexpected output: %s", res.Release.Manifest) 356 } 357 358 if !strings.Contains(res.Release.Manifest, "hello: Earth") { 359 t.Errorf("Should contain partial content. %s", res.Release.Manifest) 360 } 361 362 if strings.Contains(res.Release.Manifest, "hello: {{ template \"_planet\" . }}") { 363 t.Errorf("Should not contain partial templates itself. %s", res.Release.Manifest) 364 } 365 366 if strings.Contains(res.Release.Manifest, "empty") { 367 t.Errorf("Should not contain template data for an empty file. %s", res.Release.Manifest) 368 } 369 370 if _, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version); err == nil { 371 t.Errorf("Expected no stored release.") 372 } 373 374 if l := len(res.Release.Hooks); l != 1 { 375 t.Fatalf("Expected 1 hook, got %d", l) 376 } 377 378 if res.Release.Hooks[0].LastRun != nil { 379 t.Error("Expected hook to not be marked as run.") 380 } 381 382 if res.Release.Info.Description != "Dry run complete" { 383 t.Errorf("unexpected description: %s", res.Release.Info.Description) 384 } 385 } 386 387 func TestInstallRelease_NoHooks(t *testing.T) { 388 c := helm.NewContext() 389 rs := rsFixture() 390 rs.env.Releases.Create(releaseStub()) 391 392 req := &services.InstallReleaseRequest{ 393 Chart: chartStub(), 394 DisableHooks: true, 395 } 396 res, err := rs.InstallRelease(c, req) 397 if err != nil { 398 t.Errorf("Failed install: %s", err) 399 } 400 401 if hl := res.Release.Hooks[0].LastRun; hl != nil { 402 t.Errorf("Expected that no hooks were run. Got %d", hl) 403 } 404 } 405 406 func TestInstallRelease_FailedHooks(t *testing.T) { 407 c := helm.NewContext() 408 rs := rsFixture() 409 rs.env.Releases.Create(releaseStub()) 410 rs.env.KubeClient = newHookFailingKubeClient() 411 412 req := &services.InstallReleaseRequest{ 413 Chart: chartStub(), 414 } 415 res, err := rs.InstallRelease(c, req) 416 if err == nil { 417 t.Error("Expected failed install") 418 } 419 420 if hl := res.Release.Info.Status.Code; hl != release.Status_FAILED { 421 t.Errorf("Expected FAILED release. Got %d", hl) 422 } 423 } 424 425 func TestInstallRelease_ReuseName(t *testing.T) { 426 c := helm.NewContext() 427 rs := rsFixture() 428 rel := releaseStub() 429 rel.Info.Status.Code = release.Status_DELETED 430 rs.env.Releases.Create(rel) 431 432 req := &services.InstallReleaseRequest{ 433 Chart: chartStub(), 434 ReuseName: true, 435 Name: rel.Name, 436 } 437 res, err := rs.InstallRelease(c, req) 438 if err != nil { 439 t.Fatalf("Failed install: %s", err) 440 } 441 442 if res.Release.Name != rel.Name { 443 t.Errorf("expected %q, got %q", rel.Name, res.Release.Name) 444 } 445 446 getreq := &services.GetReleaseStatusRequest{Name: rel.Name, Version: 0} 447 getres, err := rs.GetReleaseStatus(c, getreq) 448 if err != nil { 449 t.Errorf("Failed to retrieve release: %s", err) 450 } 451 if getres.Info.Status.Code != release.Status_DEPLOYED { 452 t.Errorf("Release status is %q", getres.Info.Status.Code) 453 } 454 }