github.com/zoumo/helm@v2.5.0+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  }