github.com/strongmonkey/helm@v2.7.2+incompatible/cmd/helm/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 main
    18  
    19  import (
    20  	"io"
    21  	"reflect"
    22  	"regexp"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/spf13/cobra"
    27  
    28  	"k8s.io/helm/pkg/helm"
    29  )
    30  
    31  func TestInstall(t *testing.T) {
    32  	tests := []releaseCase{
    33  		// Install, base case
    34  		{
    35  			name:     "basic install",
    36  			args:     []string{"testdata/testcharts/alpine"},
    37  			flags:    strings.Split("--name aeneas", " "),
    38  			expected: "aeneas",
    39  			resp:     releaseMock(&releaseOptions{name: "aeneas"}),
    40  		},
    41  		// Install, no hooks
    42  		{
    43  			name:     "install without hooks",
    44  			args:     []string{"testdata/testcharts/alpine"},
    45  			flags:    strings.Split("--name aeneas --no-hooks", " "),
    46  			expected: "juno",
    47  			resp:     releaseMock(&releaseOptions{name: "juno"}),
    48  		},
    49  		// Install, values from cli
    50  		{
    51  			name:     "install with values",
    52  			args:     []string{"testdata/testcharts/alpine"},
    53  			flags:    strings.Split("--set foo=bar", " "),
    54  			resp:     releaseMock(&releaseOptions{name: "virgil"}),
    55  			expected: "virgil",
    56  		},
    57  		// Install, values from cli via multiple --set
    58  		{
    59  			name:     "install with multiple values",
    60  			args:     []string{"testdata/testcharts/alpine"},
    61  			flags:    strings.Split("--set foo=bar", "--set bar=foo"),
    62  			resp:     releaseMock(&releaseOptions{name: "virgil"}),
    63  			expected: "virgil",
    64  		},
    65  		// Install, values from yaml
    66  		{
    67  			name:     "install with values",
    68  			args:     []string{"testdata/testcharts/alpine"},
    69  			flags:    strings.Split("-f testdata/testcharts/alpine/extra_values.yaml", " "),
    70  			resp:     releaseMock(&releaseOptions{name: "virgil"}),
    71  			expected: "virgil",
    72  		},
    73  		// Install, values from multiple yaml
    74  		{
    75  			name:     "install with values",
    76  			args:     []string{"testdata/testcharts/alpine"},
    77  			flags:    strings.Split("-f testdata/testcharts/alpine/extra_values.yaml -f testdata/testcharts/alpine/more_values.yaml", " "),
    78  			resp:     releaseMock(&releaseOptions{name: "virgil"}),
    79  			expected: "virgil",
    80  		},
    81  		// Install, no charts
    82  		{
    83  			name: "install with no chart specified",
    84  			args: []string{},
    85  			err:  true,
    86  		},
    87  		// Install, re-use name
    88  		{
    89  			name:     "install and replace release",
    90  			args:     []string{"testdata/testcharts/alpine"},
    91  			flags:    strings.Split("--name aeneas --replace", " "),
    92  			expected: "aeneas",
    93  			resp:     releaseMock(&releaseOptions{name: "aeneas"}),
    94  		},
    95  		// Install, with timeout
    96  		{
    97  			name:     "install with a timeout",
    98  			args:     []string{"testdata/testcharts/alpine"},
    99  			flags:    strings.Split("--timeout 120", " "),
   100  			expected: "foobar",
   101  			resp:     releaseMock(&releaseOptions{name: "foobar"}),
   102  		},
   103  		// Install, with wait
   104  		{
   105  			name:     "install with a wait",
   106  			args:     []string{"testdata/testcharts/alpine"},
   107  			flags:    strings.Split("--wait", " "),
   108  			expected: "apollo",
   109  			resp:     releaseMock(&releaseOptions{name: "apollo"}),
   110  		},
   111  		// Install, using the name-template
   112  		{
   113  			name:     "install with name-template",
   114  			args:     []string{"testdata/testcharts/alpine"},
   115  			flags:    []string{"--name-template", "{{upper \"foobar\"}}"},
   116  			expected: "FOOBAR",
   117  			resp:     releaseMock(&releaseOptions{name: "FOOBAR"}),
   118  		},
   119  		// Install, perform chart verification along the way.
   120  		{
   121  			name:  "install with verification, missing provenance",
   122  			args:  []string{"testdata/testcharts/compressedchart-0.1.0.tgz"},
   123  			flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
   124  			err:   true,
   125  		},
   126  		{
   127  			name:  "install with verification, directory instead of file",
   128  			args:  []string{"testdata/testcharts/signtest"},
   129  			flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
   130  			err:   true,
   131  		},
   132  		{
   133  			name:  "install with verification, valid",
   134  			args:  []string{"testdata/testcharts/signtest-0.1.0.tgz"},
   135  			flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
   136  		},
   137  		// Install, chart with missing dependencies in /charts
   138  		{
   139  			name: "install chart with missing dependencies",
   140  			args: []string{"testdata/testcharts/chart-missing-deps"},
   141  			err:  true,
   142  		},
   143  		// Install, chart with bad requirements.yaml in /charts
   144  		{
   145  			name: "install chart with bad requirements.yaml",
   146  			args: []string{"testdata/testcharts/chart-bad-requirements"},
   147  			err:  true,
   148  		},
   149  	}
   150  
   151  	runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
   152  		return newInstallCmd(c, out)
   153  	})
   154  }
   155  
   156  type nameTemplateTestCase struct {
   157  	tpl              string
   158  	expected         string
   159  	expectedErrorStr string
   160  }
   161  
   162  func TestNameTemplate(t *testing.T) {
   163  	testCases := []nameTemplateTestCase{
   164  		// Just a straight up nop please
   165  		{
   166  			tpl:              "foobar",
   167  			expected:         "foobar",
   168  			expectedErrorStr: "",
   169  		},
   170  		// Random numbers at the end for fun & profit
   171  		{
   172  			tpl:              "foobar-{{randNumeric 6}}",
   173  			expected:         "foobar-[0-9]{6}$",
   174  			expectedErrorStr: "",
   175  		},
   176  		// Random numbers in the middle for fun & profit
   177  		{
   178  			tpl:              "foobar-{{randNumeric 4}}-baz",
   179  			expected:         "foobar-[0-9]{4}-baz$",
   180  			expectedErrorStr: "",
   181  		},
   182  		// No such function
   183  		{
   184  			tpl:              "foobar-{{randInt}}",
   185  			expected:         "",
   186  			expectedErrorStr: "function \"randInt\" not defined",
   187  		},
   188  		// Invalid template
   189  		{
   190  			tpl:              "foobar-{{",
   191  			expected:         "",
   192  			expectedErrorStr: "unexpected unclosed action",
   193  		},
   194  	}
   195  
   196  	for _, tc := range testCases {
   197  
   198  		n, err := generateName(tc.tpl)
   199  		if err != nil {
   200  			if tc.expectedErrorStr == "" {
   201  				t.Errorf("Was not expecting error, but got: %v", err)
   202  				continue
   203  			}
   204  			re, compErr := regexp.Compile(tc.expectedErrorStr)
   205  			if compErr != nil {
   206  				t.Errorf("Expected error string failed to compile: %v", compErr)
   207  				continue
   208  			}
   209  			if !re.MatchString(err.Error()) {
   210  				t.Errorf("Error didn't match for %s expected %s but got %v", tc.tpl, tc.expectedErrorStr, err)
   211  				continue
   212  			}
   213  		}
   214  		if err == nil && tc.expectedErrorStr != "" {
   215  			t.Errorf("Was expecting error %s but didn't get an error back", tc.expectedErrorStr)
   216  		}
   217  
   218  		if tc.expected != "" {
   219  			re, err := regexp.Compile(tc.expected)
   220  			if err != nil {
   221  				t.Errorf("Expected string failed to compile: %v", err)
   222  				continue
   223  			}
   224  			if !re.MatchString(n) {
   225  				t.Errorf("Returned name didn't match for %s expected %s but got %s", tc.tpl, tc.expected, n)
   226  			}
   227  		}
   228  	}
   229  }
   230  
   231  func TestMergeValues(t *testing.T) {
   232  	nestedMap := map[string]interface{}{
   233  		"foo": "bar",
   234  		"baz": map[string]string{
   235  			"cool": "stuff",
   236  		},
   237  	}
   238  	anotherNestedMap := map[string]interface{}{
   239  		"foo": "bar",
   240  		"baz": map[string]string{
   241  			"cool":    "things",
   242  			"awesome": "stuff",
   243  		},
   244  	}
   245  	flatMap := map[string]interface{}{
   246  		"foo": "bar",
   247  		"baz": "stuff",
   248  	}
   249  	anotherFlatMap := map[string]interface{}{
   250  		"testing": "fun",
   251  	}
   252  
   253  	testMap := mergeValues(flatMap, nestedMap)
   254  	equal := reflect.DeepEqual(testMap, nestedMap)
   255  	if !equal {
   256  		t.Errorf("Expected a nested map to overwrite a flat value. Expected: %v, got %v", nestedMap, testMap)
   257  	}
   258  
   259  	testMap = mergeValues(nestedMap, flatMap)
   260  	equal = reflect.DeepEqual(testMap, flatMap)
   261  	if !equal {
   262  		t.Errorf("Expected a flat value to overwrite a map. Expected: %v, got %v", flatMap, testMap)
   263  	}
   264  
   265  	testMap = mergeValues(nestedMap, anotherNestedMap)
   266  	equal = reflect.DeepEqual(testMap, anotherNestedMap)
   267  	if !equal {
   268  		t.Errorf("Expected a nested map to overwrite another nested map. Expected: %v, got %v", anotherNestedMap, testMap)
   269  	}
   270  
   271  	testMap = mergeValues(anotherFlatMap, anotherNestedMap)
   272  	expectedMap := map[string]interface{}{
   273  		"testing": "fun",
   274  		"foo":     "bar",
   275  		"baz": map[string]string{
   276  			"cool":    "things",
   277  			"awesome": "stuff",
   278  		},
   279  	}
   280  	equal = reflect.DeepEqual(testMap, expectedMap)
   281  	if !equal {
   282  		t.Errorf("Expected a map with different keys to merge properly with another map. Expected: %v, got %v", expectedMap, testMap)
   283  	}
   284  }