github.com/latiif/helm@v2.15.0+incompatible/cmd/helm/helm_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 main
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"regexp"
    27  	"strings"
    28  	"testing"
    29  
    30  	"github.com/spf13/cobra"
    31  
    32  	"k8s.io/client-go/util/homedir"
    33  	"k8s.io/helm/cmd/helm/installer"
    34  	"k8s.io/helm/pkg/helm"
    35  	"k8s.io/helm/pkg/helm/environment"
    36  	"k8s.io/helm/pkg/helm/helmpath"
    37  	"k8s.io/helm/pkg/proto/hapi/release"
    38  	"k8s.io/helm/pkg/repo"
    39  )
    40  
    41  // releaseCmd is a command that works with a FakeClient
    42  type releaseCmd func(c *helm.FakeClient, out io.Writer) *cobra.Command
    43  
    44  // runReleaseCases runs a set of release cases through the given releaseCmd.
    45  func runReleaseCases(t *testing.T, tests []releaseCase, rcmd releaseCmd) {
    46  	var buf bytes.Buffer
    47  	for _, tt := range tests {
    48  		t.Run(tt.name, func(t *testing.T) {
    49  			c := &helm.FakeClient{
    50  				Rels:      tt.rels,
    51  				Responses: tt.responses,
    52  			}
    53  			cmd := rcmd(c, &buf)
    54  			cmd.ParseFlags(tt.flags)
    55  			err := cmd.RunE(cmd, tt.args)
    56  			if (err != nil) != tt.err {
    57  				t.Errorf("expected error, got '%v'", err)
    58  			}
    59  			re := regexp.MustCompile(tt.expected)
    60  			if !re.Match(buf.Bytes()) {
    61  				t.Errorf("expected\n%q\ngot\n%q", tt.expected, buf.String())
    62  			}
    63  			buf.Reset()
    64  		})
    65  	}
    66  }
    67  
    68  // releaseCase describes a test case that works with releases.
    69  type releaseCase struct {
    70  	name  string
    71  	args  []string
    72  	flags []string
    73  	// expected is the string to be matched. This supports regular expressions.
    74  	expected string
    75  	err      bool
    76  	resp     *release.Release
    77  	// Rels are the available releases at the start of the test.
    78  	rels      []*release.Release
    79  	responses map[string]release.TestRun_Status
    80  }
    81  
    82  // tempHelmHome sets up a Helm Home in a temp dir.
    83  //
    84  // This does not clean up the directory. You must do that yourself.
    85  // You  must also set helmHome yourself.
    86  func tempHelmHome(t *testing.T) (helmpath.Home, error) {
    87  	oldhome := settings.Home
    88  	dir, err := ioutil.TempDir("", "helm_home-")
    89  	if err != nil {
    90  		return helmpath.Home("n/"), err
    91  	}
    92  
    93  	settings.Home = helmpath.Home(dir)
    94  	if err := ensureTestHome(settings.Home, t); err != nil {
    95  		return helmpath.Home("n/"), err
    96  	}
    97  	settings.Home = oldhome
    98  	return helmpath.Home(dir), nil
    99  }
   100  
   101  // ensureTestHome creates a home directory like ensureHome, but without remote references.
   102  //
   103  // t is used only for logging.
   104  func ensureTestHome(home helmpath.Home, t *testing.T) error {
   105  	configDirectories := []string{home.String(), home.Repository(), home.Cache(), home.LocalRepository(), home.Plugins(), home.Starters()}
   106  	for _, p := range configDirectories {
   107  		if fi, err := os.Stat(p); err != nil {
   108  			if err := os.MkdirAll(p, 0755); err != nil {
   109  				return fmt.Errorf("Could not create %s: %s", p, err)
   110  			}
   111  		} else if !fi.IsDir() {
   112  			return fmt.Errorf("%s must be a directory", p)
   113  		}
   114  	}
   115  
   116  	repoFile := home.RepositoryFile()
   117  	if fi, err := os.Stat(repoFile); err != nil {
   118  		rf := repo.NewRepoFile()
   119  		rf.Add(&repo.Entry{
   120  			Name:  "charts",
   121  			URL:   "http://example.com/foo",
   122  			Cache: "charts-index.yaml",
   123  		}, &repo.Entry{
   124  			Name:  "local",
   125  			URL:   "http://localhost.com:7743/foo",
   126  			Cache: "local-index.yaml",
   127  		})
   128  		if err := rf.WriteFile(repoFile, 0644); err != nil {
   129  			return err
   130  		}
   131  	} else if fi.IsDir() {
   132  		return fmt.Errorf("%s must be a file, not a directory", repoFile)
   133  	}
   134  	if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate {
   135  		t.Log("Updating repository file format...")
   136  		if err := r.WriteFile(repoFile, 0644); err != nil {
   137  			return err
   138  		}
   139  	}
   140  
   141  	localRepoIndexFile := home.LocalRepository(installer.LocalRepositoryIndexFile)
   142  	if fi, err := os.Stat(localRepoIndexFile); err != nil {
   143  		i := repo.NewIndexFile()
   144  		if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {
   145  			return err
   146  		}
   147  
   148  		//TODO: take this out and replace with helm update functionality
   149  		os.Symlink(localRepoIndexFile, home.CacheIndex("local"))
   150  	} else if fi.IsDir() {
   151  		return fmt.Errorf("%s must be a file, not a directory", localRepoIndexFile)
   152  	}
   153  
   154  	t.Logf("$HELM_HOME has been configured at %s.\n", settings.Home.String())
   155  	return nil
   156  
   157  }
   158  
   159  func TestRootCmd(t *testing.T) {
   160  	cleanup := resetEnv()
   161  	defer cleanup()
   162  
   163  	tests := []struct {
   164  		name   string
   165  		args   []string
   166  		envars map[string]string
   167  		home   string
   168  	}{
   169  		{
   170  			name: "defaults",
   171  			args: []string{"home"},
   172  			home: filepath.Join(homedir.HomeDir(), ".helm"),
   173  		},
   174  		{
   175  			name: "with --home set",
   176  			args: []string{"--home", "/foo"},
   177  			home: "/foo",
   178  		},
   179  		{
   180  			name: "subcommands with --home set",
   181  			args: []string{"home", "--home", "/foo"},
   182  			home: "/foo",
   183  		},
   184  		{
   185  			name:   "with $HELM_HOME set",
   186  			args:   []string{"home"},
   187  			envars: map[string]string{"HELM_HOME": "/bar"},
   188  			home:   "/bar",
   189  		},
   190  		{
   191  			name:   "subcommands with $HELM_HOME set",
   192  			args:   []string{"home"},
   193  			envars: map[string]string{"HELM_HOME": "/bar"},
   194  			home:   "/bar",
   195  		},
   196  		{
   197  			name:   "with $HELM_HOME and --home set",
   198  			args:   []string{"home", "--home", "/foo"},
   199  			envars: map[string]string{"HELM_HOME": "/bar"},
   200  			home:   "/foo",
   201  		},
   202  	}
   203  
   204  	// ensure not set locally
   205  	os.Unsetenv("HELM_HOME")
   206  
   207  	for _, tt := range tests {
   208  		t.Run(tt.name, func(t *testing.T) {
   209  			defer os.Unsetenv("HELM_HOME")
   210  
   211  			for k, v := range tt.envars {
   212  				os.Setenv(k, v)
   213  			}
   214  
   215  			cmd := newRootCmd(tt.args)
   216  			cmd.SetOutput(ioutil.Discard)
   217  			cmd.SetArgs(tt.args)
   218  			cmd.Run = func(*cobra.Command, []string) {}
   219  			if err := cmd.Execute(); err != nil {
   220  				t.Errorf("unexpected error: %s", err)
   221  			}
   222  
   223  			if settings.Home.String() != tt.home {
   224  				t.Errorf("expected home %q, got %q", tt.home, settings.Home)
   225  			}
   226  			homeFlag := cmd.Flag("home").Value.String()
   227  			homeFlag = os.ExpandEnv(homeFlag)
   228  			if homeFlag != tt.home {
   229  				t.Errorf("expected home %q, got %q", tt.home, homeFlag)
   230  			}
   231  		})
   232  	}
   233  }
   234  
   235  func TestTLSFlags(t *testing.T) {
   236  	cleanup := resetEnv()
   237  	defer cleanup()
   238  
   239  	homePath := os.Getenv("HELM_HOME")
   240  	if homePath == "" {
   241  		homePath = filepath.Join(homedir.HomeDir(), ".helm")
   242  	}
   243  
   244  	home := helmpath.Home(homePath)
   245  
   246  	tests := []struct {
   247  		name     string
   248  		args     []string
   249  		envars   map[string]string
   250  		settings environment.EnvSettings
   251  	}{
   252  		{
   253  			name: "defaults",
   254  			args: []string{"version", "-c"},
   255  			settings: environment.EnvSettings{
   256  				TillerHost:              "",
   257  				TillerConnectionTimeout: 300,
   258  				TillerNamespace:         "kube-system",
   259  				Home:                    home,
   260  				Debug:                   false,
   261  				KubeContext:             "",
   262  				KubeConfig:              "",
   263  				TLSEnable:               false,
   264  				TLSVerify:               false,
   265  				TLSServerName:           "",
   266  				TLSCaCertFile:           home.TLSCaCert(),
   267  				TLSCertFile:             home.TLSCert(),
   268  				TLSKeyFile:              home.TLSKey(),
   269  			},
   270  		},
   271  		{
   272  			name: "tls enable",
   273  			args: []string{"version", "-c", "--tls"},
   274  			settings: environment.EnvSettings{
   275  				TillerHost:              "",
   276  				TillerConnectionTimeout: 300,
   277  				TillerNamespace:         "kube-system",
   278  				Home:                    home,
   279  				Debug:                   false,
   280  				KubeContext:             "",
   281  				KubeConfig:              "",
   282  				TLSEnable:               true,
   283  				TLSVerify:               false,
   284  				TLSServerName:           "",
   285  				TLSCaCertFile:           home.TLSCaCert(),
   286  				TLSCertFile:             home.TLSCert(),
   287  				TLSKeyFile:              home.TLSKey(),
   288  			},
   289  		},
   290  		{
   291  			name: "tls verify",
   292  			args: []string{"version", "-c", "--tls-verify"},
   293  			settings: environment.EnvSettings{
   294  				TillerHost:              "",
   295  				TillerConnectionTimeout: 300,
   296  				TillerNamespace:         "kube-system",
   297  				Home:                    home,
   298  				Debug:                   false,
   299  				KubeContext:             "",
   300  				KubeConfig:              "",
   301  				TLSEnable:               false,
   302  				TLSVerify:               true,
   303  				TLSServerName:           "",
   304  				TLSCaCertFile:           home.TLSCaCert(),
   305  				TLSCertFile:             home.TLSCert(),
   306  				TLSKeyFile:              home.TLSKey(),
   307  			},
   308  		},
   309  		{
   310  			name: "tls servername",
   311  			args: []string{"version", "-c", "--tls-hostname=foo"},
   312  			settings: environment.EnvSettings{
   313  				TillerHost:              "",
   314  				TillerConnectionTimeout: 300,
   315  				TillerNamespace:         "kube-system",
   316  				Home:                    home,
   317  				Debug:                   false,
   318  				KubeContext:             "",
   319  				KubeConfig:              "",
   320  				TLSEnable:               false,
   321  				TLSVerify:               false,
   322  				TLSServerName:           "foo",
   323  				TLSCaCertFile:           home.TLSCaCert(),
   324  				TLSCertFile:             home.TLSCert(),
   325  				TLSKeyFile:              home.TLSKey(),
   326  			},
   327  		},
   328  		{
   329  			name: "tls cacert",
   330  			args: []string{"version", "-c", "--tls-ca-cert=/foo"},
   331  			settings: environment.EnvSettings{
   332  				TillerHost:              "",
   333  				TillerConnectionTimeout: 300,
   334  				TillerNamespace:         "kube-system",
   335  				Home:                    home,
   336  				Debug:                   false,
   337  				KubeContext:             "",
   338  				KubeConfig:              "",
   339  				TLSEnable:               false,
   340  				TLSVerify:               false,
   341  				TLSServerName:           "",
   342  				TLSCaCertFile:           "/foo",
   343  				TLSCertFile:             home.TLSCert(),
   344  				TLSKeyFile:              home.TLSKey(),
   345  			},
   346  		},
   347  		{
   348  			name: "tls cert",
   349  			args: []string{"version", "-c", "--tls-cert=/foo"},
   350  			settings: environment.EnvSettings{
   351  				TillerHost:              "",
   352  				TillerConnectionTimeout: 300,
   353  				TillerNamespace:         "kube-system",
   354  				Home:                    home,
   355  				Debug:                   false,
   356  				KubeContext:             "",
   357  				KubeConfig:              "",
   358  				TLSEnable:               false,
   359  				TLSVerify:               false,
   360  				TLSServerName:           "",
   361  				TLSCaCertFile:           home.TLSCaCert(),
   362  				TLSCertFile:             "/foo",
   363  				TLSKeyFile:              home.TLSKey(),
   364  			},
   365  		},
   366  		{
   367  			name: "tls key",
   368  			args: []string{"version", "-c", "--tls-key=/foo"},
   369  			settings: environment.EnvSettings{
   370  				TillerHost:              "",
   371  				TillerConnectionTimeout: 300,
   372  				TillerNamespace:         "kube-system",
   373  				Home:                    home,
   374  				Debug:                   false,
   375  				KubeContext:             "",
   376  				KubeConfig:              "",
   377  				TLSEnable:               false,
   378  				TLSVerify:               false,
   379  				TLSServerName:           "",
   380  				TLSCaCertFile:           home.TLSCaCert(),
   381  				TLSCertFile:             home.TLSCert(),
   382  				TLSKeyFile:              "/foo",
   383  			},
   384  		},
   385  		{
   386  			name:   "tls enable envvar",
   387  			args:   []string{"version", "-c"},
   388  			envars: map[string]string{"HELM_TLS_ENABLE": "true"},
   389  			settings: environment.EnvSettings{
   390  				TillerHost:              "",
   391  				TillerConnectionTimeout: 300,
   392  				TillerNamespace:         "kube-system",
   393  				Home:                    home,
   394  				Debug:                   false,
   395  				KubeContext:             "",
   396  				KubeConfig:              "",
   397  				TLSEnable:               true,
   398  				TLSVerify:               false,
   399  				TLSServerName:           "",
   400  				TLSCaCertFile:           home.TLSCaCert(),
   401  				TLSCertFile:             home.TLSCert(),
   402  				TLSKeyFile:              home.TLSKey(),
   403  			},
   404  		},
   405  		{
   406  			name:   "tls verify envvar",
   407  			args:   []string{"version", "-c"},
   408  			envars: map[string]string{"HELM_TLS_VERIFY": "true"},
   409  			settings: environment.EnvSettings{
   410  				TillerHost:              "",
   411  				TillerConnectionTimeout: 300,
   412  				TillerNamespace:         "kube-system",
   413  				Home:                    home,
   414  				Debug:                   false,
   415  				KubeContext:             "",
   416  				KubeConfig:              "",
   417  				TLSEnable:               false,
   418  				TLSVerify:               true,
   419  				TLSServerName:           "",
   420  				TLSCaCertFile:           home.TLSCaCert(),
   421  				TLSCertFile:             home.TLSCert(),
   422  				TLSKeyFile:              home.TLSKey(),
   423  			},
   424  		},
   425  		{
   426  			name:   "tls servername envvar",
   427  			args:   []string{"version", "-c"},
   428  			envars: map[string]string{"HELM_TLS_HOSTNAME": "foo"},
   429  			settings: environment.EnvSettings{
   430  				TillerHost:              "",
   431  				TillerConnectionTimeout: 300,
   432  				TillerNamespace:         "kube-system",
   433  				Home:                    home,
   434  				Debug:                   false,
   435  				KubeContext:             "",
   436  				KubeConfig:              "",
   437  				TLSEnable:               false,
   438  				TLSVerify:               false,
   439  				TLSServerName:           "foo",
   440  				TLSCaCertFile:           home.TLSCaCert(),
   441  				TLSCertFile:             home.TLSCert(),
   442  				TLSKeyFile:              home.TLSKey(),
   443  			},
   444  		},
   445  		{
   446  			name:   "tls cacert envvar",
   447  			args:   []string{"version", "-c"},
   448  			envars: map[string]string{"HELM_TLS_CA_CERT": "/foo"},
   449  			settings: environment.EnvSettings{
   450  				TillerHost:              "",
   451  				TillerConnectionTimeout: 300,
   452  				TillerNamespace:         "kube-system",
   453  				Home:                    home,
   454  				Debug:                   false,
   455  				KubeContext:             "",
   456  				KubeConfig:              "",
   457  				TLSEnable:               false,
   458  				TLSVerify:               false,
   459  				TLSServerName:           "",
   460  				TLSCaCertFile:           "/foo",
   461  				TLSCertFile:             home.TLSCert(),
   462  				TLSKeyFile:              home.TLSKey(),
   463  			},
   464  		},
   465  		{
   466  			name:   "tls cert envvar",
   467  			args:   []string{"version", "-c"},
   468  			envars: map[string]string{"HELM_TLS_CERT": "/foo"},
   469  			settings: environment.EnvSettings{
   470  				TillerHost:              "",
   471  				TillerConnectionTimeout: 300,
   472  				TillerNamespace:         "kube-system",
   473  				Home:                    home,
   474  				Debug:                   false,
   475  				KubeContext:             "",
   476  				KubeConfig:              "",
   477  				TLSEnable:               false,
   478  				TLSVerify:               false,
   479  				TLSServerName:           "",
   480  				TLSCaCertFile:           home.TLSCaCert(),
   481  				TLSCertFile:             "/foo",
   482  				TLSKeyFile:              home.TLSKey(),
   483  			},
   484  		},
   485  		{
   486  			name:   "tls key envvar",
   487  			args:   []string{"version", "-c"},
   488  			envars: map[string]string{"HELM_TLS_KEY": "/foo"},
   489  			settings: environment.EnvSettings{
   490  				TillerHost:              "",
   491  				TillerConnectionTimeout: 300,
   492  				TillerNamespace:         "kube-system",
   493  				Home:                    home,
   494  				Debug:                   false,
   495  				KubeContext:             "",
   496  				KubeConfig:              "",
   497  				TLSEnable:               false,
   498  				TLSVerify:               false,
   499  				TLSServerName:           "",
   500  				TLSCaCertFile:           home.TLSCaCert(),
   501  				TLSCertFile:             home.TLSCert(),
   502  				TLSKeyFile:              "/foo",
   503  			},
   504  		},
   505  	}
   506  
   507  	// ensure not set locally
   508  	tlsEnvvars := []string{
   509  		"HELM_TLS_HOSTNAME",
   510  		"HELM_TLS_CA_CERT",
   511  		"HELM_TLS_CERT",
   512  		"HELM_TLS_KEY",
   513  		"HELM_TLS_VERIFY",
   514  		"HELM_TLS_ENABLE",
   515  	}
   516  
   517  	for i := range tlsEnvvars {
   518  		os.Unsetenv(tlsEnvvars[i])
   519  	}
   520  
   521  	for _, tt := range tests {
   522  		t.Run(tt.name, func(t *testing.T) {
   523  
   524  			for k, v := range tt.envars {
   525  				os.Setenv(k, v)
   526  				defer os.Unsetenv(k)
   527  			}
   528  
   529  			cmd := newRootCmd(tt.args)
   530  			cmd.SetOutput(ioutil.Discard)
   531  			cmd.SetArgs(tt.args)
   532  			cmd.Run = func(*cobra.Command, []string) {}
   533  			if err := cmd.Execute(); err != nil {
   534  				t.Errorf("unexpected error: %s", err)
   535  			}
   536  
   537  			if settings != tt.settings {
   538  				t.Errorf("expected settings %v, got %v", tt.settings, settings)
   539  			}
   540  		})
   541  	}
   542  }
   543  
   544  func resetEnv() func() {
   545  	origSettings := settings
   546  	origEnv := os.Environ()
   547  	return func() {
   548  		settings = origSettings
   549  		for _, pair := range origEnv {
   550  			kv := strings.SplitN(pair, "=", 2)
   551  			os.Setenv(kv[0], kv[1])
   552  		}
   553  	}
   554  }