github.com/azlyth/helm@v2.8.2+incompatible/pkg/tiller/release_update_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  	"strings"
    21  	"testing"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  
    25  	"k8s.io/helm/pkg/helm"
    26  	"k8s.io/helm/pkg/proto/hapi/chart"
    27  	"k8s.io/helm/pkg/proto/hapi/release"
    28  	"k8s.io/helm/pkg/proto/hapi/services"
    29  )
    30  
    31  func TestUpdateRelease(t *testing.T) {
    32  	c := helm.NewContext()
    33  	rs := rsFixture()
    34  	rel := releaseStub()
    35  	rs.env.Releases.Create(rel)
    36  
    37  	req := &services.UpdateReleaseRequest{
    38  		Name: rel.Name,
    39  		Chart: &chart.Chart{
    40  			Metadata: &chart.Metadata{Name: "hello"},
    41  			Templates: []*chart.Template{
    42  				{Name: "templates/hello", Data: []byte("hello: world")},
    43  				{Name: "templates/hooks", Data: []byte(manifestWithUpgradeHooks)},
    44  			},
    45  		},
    46  	}
    47  	res, err := rs.UpdateRelease(c, req)
    48  	if err != nil {
    49  		t.Fatalf("Failed updated: %s", err)
    50  	}
    51  
    52  	if res.Release.Name == "" {
    53  		t.Errorf("Expected release name.")
    54  	}
    55  
    56  	if res.Release.Name != rel.Name {
    57  		t.Errorf("Updated release name does not match previous release name. Expected %s, got %s", rel.Name, res.Release.Name)
    58  	}
    59  
    60  	if res.Release.Namespace != rel.Namespace {
    61  		t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Release.Namespace)
    62  	}
    63  
    64  	updated := compareStoredAndReturnedRelease(t, *rs, *res)
    65  
    66  	if len(updated.Hooks) != 1 {
    67  		t.Fatalf("Expected 1 hook, got %d", len(updated.Hooks))
    68  	}
    69  	if updated.Hooks[0].Manifest != manifestWithUpgradeHooks {
    70  		t.Errorf("Unexpected manifest: %v", updated.Hooks[0].Manifest)
    71  	}
    72  
    73  	if updated.Hooks[0].Events[0] != release.Hook_POST_UPGRADE {
    74  		t.Errorf("Expected event 0 to be post upgrade")
    75  	}
    76  
    77  	if updated.Hooks[0].Events[1] != release.Hook_PRE_UPGRADE {
    78  		t.Errorf("Expected event 0 to be pre upgrade")
    79  	}
    80  
    81  	if len(updated.Manifest) == 0 {
    82  		t.Errorf("Expected manifest in %v", res)
    83  	}
    84  
    85  	if res.Release.Config == nil {
    86  		t.Errorf("Got release without config: %#v", res.Release)
    87  	} else if res.Release.Config.Raw != rel.Config.Raw {
    88  		t.Errorf("Expected release values %q, got %q", rel.Config.Raw, res.Release.Config.Raw)
    89  	}
    90  
    91  	if !strings.Contains(updated.Manifest, "---\n# Source: hello/templates/hello\nhello: world") {
    92  		t.Errorf("unexpected output: %s", updated.Manifest)
    93  	}
    94  
    95  	if res.Release.Version != 2 {
    96  		t.Errorf("Expected release version to be %v, got %v", 2, res.Release.Version)
    97  	}
    98  
    99  	edesc := "Upgrade complete"
   100  	if got := res.Release.Info.Description; got != edesc {
   101  		t.Errorf("Expected description %q, got %q", edesc, got)
   102  	}
   103  }
   104  func TestUpdateRelease_ResetValues(t *testing.T) {
   105  	c := helm.NewContext()
   106  	rs := rsFixture()
   107  	rel := releaseStub()
   108  	rs.env.Releases.Create(rel)
   109  
   110  	req := &services.UpdateReleaseRequest{
   111  		Name: rel.Name,
   112  		Chart: &chart.Chart{
   113  			Metadata: &chart.Metadata{Name: "hello"},
   114  			Templates: []*chart.Template{
   115  				{Name: "templates/hello", Data: []byte("hello: world")},
   116  				{Name: "templates/hooks", Data: []byte(manifestWithUpgradeHooks)},
   117  			},
   118  		},
   119  		ResetValues: true,
   120  	}
   121  	res, err := rs.UpdateRelease(c, req)
   122  	if err != nil {
   123  		t.Fatalf("Failed updated: %s", err)
   124  	}
   125  	// This should have been unset. Config:  &chart.Config{Raw: `name: value`},
   126  	if res.Release.Config != nil && res.Release.Config.Raw != "" {
   127  		t.Errorf("Expected chart config to be empty, got %q", res.Release.Config.Raw)
   128  	}
   129  }
   130  
   131  func TestUpdateRelease_ReuseValues(t *testing.T) {
   132  	c := helm.NewContext()
   133  	rs := rsFixture()
   134  	rel := releaseStub()
   135  	rs.env.Releases.Create(rel)
   136  
   137  	req := &services.UpdateReleaseRequest{
   138  		Name: rel.Name,
   139  		Chart: &chart.Chart{
   140  			Metadata: &chart.Metadata{Name: "hello"},
   141  			Templates: []*chart.Template{
   142  				{Name: "templates/hello", Data: []byte("hello: world")},
   143  				{Name: "templates/hooks", Data: []byte(manifestWithUpgradeHooks)},
   144  			},
   145  			// Since reuseValues is set, this should get ignored.
   146  			Values: &chart.Config{Raw: "foo: bar\n"},
   147  		},
   148  		Values:      &chart.Config{Raw: "name2: val2"},
   149  		ReuseValues: true,
   150  	}
   151  	res, err := rs.UpdateRelease(c, req)
   152  	if err != nil {
   153  		t.Fatalf("Failed updated: %s", err)
   154  	}
   155  	// This should have been overwritten with the old value.
   156  	expect := "name: value\n"
   157  	if res.Release.Chart.Values != nil && res.Release.Chart.Values.Raw != expect {
   158  		t.Errorf("Expected chart values to be %q, got %q", expect, res.Release.Chart.Values.Raw)
   159  	}
   160  	// This should have the newly-passed overrides.
   161  	expect = "name2: val2"
   162  	if res.Release.Config != nil && res.Release.Config.Raw != expect {
   163  		t.Errorf("Expected request config to be %q, got %q", expect, res.Release.Config.Raw)
   164  	}
   165  	compareStoredAndReturnedRelease(t, *rs, *res)
   166  }
   167  
   168  func TestUpdateRelease_ResetReuseValues(t *testing.T) {
   169  	// This verifies that when both reset and reuse are set, reset wins.
   170  	c := helm.NewContext()
   171  	rs := rsFixture()
   172  	rel := releaseStub()
   173  	rs.env.Releases.Create(rel)
   174  
   175  	req := &services.UpdateReleaseRequest{
   176  		Name: rel.Name,
   177  		Chart: &chart.Chart{
   178  			Metadata: &chart.Metadata{Name: "hello"},
   179  			Templates: []*chart.Template{
   180  				{Name: "templates/hello", Data: []byte("hello: world")},
   181  				{Name: "templates/hooks", Data: []byte(manifestWithUpgradeHooks)},
   182  			},
   183  		},
   184  		ResetValues: true,
   185  		ReuseValues: true,
   186  	}
   187  	res, err := rs.UpdateRelease(c, req)
   188  	if err != nil {
   189  		t.Fatalf("Failed updated: %s", err)
   190  	}
   191  	// This should have been unset. Config:  &chart.Config{Raw: `name: value`},
   192  	if res.Release.Config != nil && res.Release.Config.Raw != "" {
   193  		t.Errorf("Expected chart config to be empty, got %q", res.Release.Config.Raw)
   194  	}
   195  	compareStoredAndReturnedRelease(t, *rs, *res)
   196  }
   197  
   198  func TestUpdateReleaseFailure(t *testing.T) {
   199  	c := helm.NewContext()
   200  	rs := rsFixture()
   201  	rel := releaseStub()
   202  	rs.env.Releases.Create(rel)
   203  	rs.env.KubeClient = newUpdateFailingKubeClient()
   204  	rs.Log = t.Logf
   205  
   206  	req := &services.UpdateReleaseRequest{
   207  		Name:         rel.Name,
   208  		DisableHooks: true,
   209  		Chart: &chart.Chart{
   210  			Metadata: &chart.Metadata{Name: "hello"},
   211  			Templates: []*chart.Template{
   212  				{Name: "templates/something", Data: []byte("hello: world")},
   213  			},
   214  		},
   215  	}
   216  
   217  	res, err := rs.UpdateRelease(c, req)
   218  	if err == nil {
   219  		t.Error("Expected failed update")
   220  	}
   221  
   222  	if updatedStatus := res.Release.Info.Status.Code; updatedStatus != release.Status_FAILED {
   223  		t.Errorf("Expected FAILED release. Got %d", updatedStatus)
   224  	}
   225  
   226  	compareStoredAndReturnedRelease(t, *rs, *res)
   227  
   228  	expectedDescription := "Upgrade \"angry-panda\" failed: Failed update in kube client"
   229  	if got := res.Release.Info.Description; got != expectedDescription {
   230  		t.Errorf("Expected description %q, got %q", expectedDescription, got)
   231  	}
   232  
   233  	oldRelease, err := rs.env.Releases.Get(rel.Name, rel.Version)
   234  	if err != nil {
   235  		t.Errorf("Expected to be able to get previous release")
   236  	}
   237  	if oldStatus := oldRelease.Info.Status.Code; oldStatus != release.Status_DEPLOYED {
   238  		t.Errorf("Expected Deployed status on previous Release version. Got %v", oldStatus)
   239  	}
   240  }
   241  
   242  func TestUpdateReleaseFailure_Force(t *testing.T) {
   243  	c := helm.NewContext()
   244  	rs := rsFixture()
   245  	rel := namedReleaseStub("forceful-luke", release.Status_FAILED)
   246  	rs.env.Releases.Create(rel)
   247  	rs.Log = t.Logf
   248  
   249  	req := &services.UpdateReleaseRequest{
   250  		Name:         rel.Name,
   251  		DisableHooks: true,
   252  		Chart: &chart.Chart{
   253  			Metadata: &chart.Metadata{Name: "hello"},
   254  			Templates: []*chart.Template{
   255  				{Name: "templates/something", Data: []byte("text: 'Did you ever hear the tragedy of Darth Plagueis the Wise? I thought not. It’s not a story the Jedi would tell you. It’s a Sith legend. Darth Plagueis was a Dark Lord of the Sith, so powerful and so wise he could use the Force to influence the Midichlorians to create life... He had such a knowledge of the Dark Side that he could even keep the ones he cared about from dying. The Dark Side of the Force is a pathway to many abilities some consider to be unnatural. He became so powerful... The only thing he was afraid of was losing his power, which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew, then his apprentice killed him in his sleep. Ironic. He could save others from death, but not himself.'")},
   256  			},
   257  		},
   258  		Force: true,
   259  	}
   260  
   261  	res, err := rs.UpdateRelease(c, req)
   262  	if err != nil {
   263  		t.Errorf("Expected successful update, got %v", err)
   264  	}
   265  
   266  	if updatedStatus := res.Release.Info.Status.Code; updatedStatus != release.Status_DEPLOYED {
   267  		t.Errorf("Expected DEPLOYED release. Got %d", updatedStatus)
   268  	}
   269  
   270  	compareStoredAndReturnedRelease(t, *rs, *res)
   271  
   272  	expectedDescription := "Upgrade complete"
   273  	if got := res.Release.Info.Description; got != expectedDescription {
   274  		t.Errorf("Expected description %q, got %q", expectedDescription, got)
   275  	}
   276  
   277  	oldRelease, err := rs.env.Releases.Get(rel.Name, rel.Version)
   278  	if err != nil {
   279  		t.Errorf("Expected to be able to get previous release")
   280  	}
   281  	if oldStatus := oldRelease.Info.Status.Code; oldStatus != release.Status_DELETED {
   282  		t.Errorf("Expected Deleted status on previous Release version. Got %v", oldStatus)
   283  	}
   284  }
   285  
   286  func TestUpdateReleaseNoHooks(t *testing.T) {
   287  	c := helm.NewContext()
   288  	rs := rsFixture()
   289  	rel := releaseStub()
   290  	rs.env.Releases.Create(rel)
   291  
   292  	req := &services.UpdateReleaseRequest{
   293  		Name:         rel.Name,
   294  		DisableHooks: true,
   295  		Chart: &chart.Chart{
   296  			Metadata: &chart.Metadata{Name: "hello"},
   297  			Templates: []*chart.Template{
   298  				{Name: "templates/hello", Data: []byte("hello: world")},
   299  				{Name: "templates/hooks", Data: []byte(manifestWithUpgradeHooks)},
   300  			},
   301  		},
   302  	}
   303  
   304  	res, err := rs.UpdateRelease(c, req)
   305  	if err != nil {
   306  		t.Fatalf("Failed updated: %s", err)
   307  	}
   308  
   309  	if hl := res.Release.Hooks[0].LastRun; hl != nil {
   310  		t.Errorf("Expected that no hooks were run. Got %d", hl)
   311  	}
   312  
   313  }
   314  
   315  func TestUpdateReleaseNoChanges(t *testing.T) {
   316  	c := helm.NewContext()
   317  	rs := rsFixture()
   318  	rel := releaseStub()
   319  	rs.env.Releases.Create(rel)
   320  
   321  	req := &services.UpdateReleaseRequest{
   322  		Name:         rel.Name,
   323  		DisableHooks: true,
   324  		Chart:        rel.GetChart(),
   325  	}
   326  
   327  	_, err := rs.UpdateRelease(c, req)
   328  	if err != nil {
   329  		t.Fatalf("Failed updated: %s", err)
   330  	}
   331  }
   332  
   333  func compareStoredAndReturnedRelease(t *testing.T, rs ReleaseServer, res services.UpdateReleaseResponse) *release.Release {
   334  	storedRelease, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version)
   335  	if err != nil {
   336  		t.Fatalf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases)
   337  	}
   338  
   339  	if !proto.Equal(storedRelease, res.Release) {
   340  		t.Errorf("Stored release doesn't match returned Release")
   341  	}
   342  
   343  	return storedRelease
   344  }