github.com/valdemarpavesi/helm@v2.9.1+incompatible/cmd/helm/helm_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  	"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/helm/pkg/helm"
    33  	"k8s.io/helm/pkg/helm/helmpath"
    34  	"k8s.io/helm/pkg/proto/hapi/release"
    35  	"k8s.io/helm/pkg/repo"
    36  )
    37  
    38  // releaseCmd is a command that works with a FakeClient
    39  type releaseCmd func(c *helm.FakeClient, out io.Writer) *cobra.Command
    40  
    41  // runReleaseCases runs a set of release cases through the given releaseCmd.
    42  func runReleaseCases(t *testing.T, tests []releaseCase, rcmd releaseCmd) {
    43  	var buf bytes.Buffer
    44  	for _, tt := range tests {
    45  		t.Run(tt.name, func(t *testing.T) {
    46  			c := &helm.FakeClient{Rels: tt.rels}
    47  			cmd := rcmd(c, &buf)
    48  			cmd.ParseFlags(tt.flags)
    49  			err := cmd.RunE(cmd, tt.args)
    50  			if (err != nil) != tt.err {
    51  				t.Errorf("expected error, got '%v'", err)
    52  			}
    53  			re := regexp.MustCompile(tt.expected)
    54  			if !re.Match(buf.Bytes()) {
    55  				t.Errorf("expected\n%q\ngot\n%q", tt.expected, buf.String())
    56  			}
    57  			buf.Reset()
    58  		})
    59  	}
    60  }
    61  
    62  // releaseCase describes a test case that works with releases.
    63  type releaseCase struct {
    64  	name  string
    65  	args  []string
    66  	flags []string
    67  	// expected is the string to be matched. This supports regular expressions.
    68  	expected string
    69  	err      bool
    70  	resp     *release.Release
    71  	// Rels are the available releases at the start of the test.
    72  	rels []*release.Release
    73  }
    74  
    75  // tempHelmHome sets up a Helm Home in a temp dir.
    76  //
    77  // This does not clean up the directory. You must do that yourself.
    78  // You  must also set helmHome yourself.
    79  func tempHelmHome(t *testing.T) (helmpath.Home, error) {
    80  	oldhome := settings.Home
    81  	dir, err := ioutil.TempDir("", "helm_home-")
    82  	if err != nil {
    83  		return helmpath.Home("n/"), err
    84  	}
    85  
    86  	settings.Home = helmpath.Home(dir)
    87  	if err := ensureTestHome(settings.Home, t); err != nil {
    88  		return helmpath.Home("n/"), err
    89  	}
    90  	settings.Home = oldhome
    91  	return helmpath.Home(dir), nil
    92  }
    93  
    94  // ensureTestHome creates a home directory like ensureHome, but without remote references.
    95  //
    96  // t is used only for logging.
    97  func ensureTestHome(home helmpath.Home, t *testing.T) error {
    98  	configDirectories := []string{home.String(), home.Repository(), home.Cache(), home.LocalRepository(), home.Plugins(), home.Starters()}
    99  	for _, p := range configDirectories {
   100  		if fi, err := os.Stat(p); err != nil {
   101  			if err := os.MkdirAll(p, 0755); err != nil {
   102  				return fmt.Errorf("Could not create %s: %s", p, err)
   103  			}
   104  		} else if !fi.IsDir() {
   105  			return fmt.Errorf("%s must be a directory", p)
   106  		}
   107  	}
   108  
   109  	repoFile := home.RepositoryFile()
   110  	if fi, err := os.Stat(repoFile); err != nil {
   111  		rf := repo.NewRepoFile()
   112  		rf.Add(&repo.Entry{
   113  			Name:  "charts",
   114  			URL:   "http://example.com/foo",
   115  			Cache: "charts-index.yaml",
   116  		}, &repo.Entry{
   117  			Name:  "local",
   118  			URL:   "http://localhost.com:7743/foo",
   119  			Cache: "local-index.yaml",
   120  		})
   121  		if err := rf.WriteFile(repoFile, 0644); err != nil {
   122  			return err
   123  		}
   124  	} else if fi.IsDir() {
   125  		return fmt.Errorf("%s must be a file, not a directory", repoFile)
   126  	}
   127  	if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate {
   128  		t.Log("Updating repository file format...")
   129  		if err := r.WriteFile(repoFile, 0644); err != nil {
   130  			return err
   131  		}
   132  	}
   133  
   134  	localRepoIndexFile := home.LocalRepository(localRepositoryIndexFile)
   135  	if fi, err := os.Stat(localRepoIndexFile); err != nil {
   136  		i := repo.NewIndexFile()
   137  		if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {
   138  			return err
   139  		}
   140  
   141  		//TODO: take this out and replace with helm update functionality
   142  		os.Symlink(localRepoIndexFile, home.CacheIndex("local"))
   143  	} else if fi.IsDir() {
   144  		return fmt.Errorf("%s must be a file, not a directory", localRepoIndexFile)
   145  	}
   146  
   147  	t.Logf("$HELM_HOME has been configured at %s.\n", settings.Home.String())
   148  	return nil
   149  
   150  }
   151  
   152  func TestRootCmd(t *testing.T) {
   153  	cleanup := resetEnv()
   154  	defer cleanup()
   155  
   156  	tests := []struct {
   157  		name   string
   158  		args   []string
   159  		envars map[string]string
   160  		home   string
   161  	}{
   162  		{
   163  			name: "defaults",
   164  			args: []string{"home"},
   165  			home: filepath.Join(os.Getenv("HOME"), "/.helm"),
   166  		},
   167  		{
   168  			name: "with --home set",
   169  			args: []string{"--home", "/foo"},
   170  			home: "/foo",
   171  		},
   172  		{
   173  			name: "subcommands with --home set",
   174  			args: []string{"home", "--home", "/foo"},
   175  			home: "/foo",
   176  		},
   177  		{
   178  			name:   "with $HELM_HOME set",
   179  			args:   []string{"home"},
   180  			envars: map[string]string{"HELM_HOME": "/bar"},
   181  			home:   "/bar",
   182  		},
   183  		{
   184  			name:   "subcommands with $HELM_HOME set",
   185  			args:   []string{"home"},
   186  			envars: map[string]string{"HELM_HOME": "/bar"},
   187  			home:   "/bar",
   188  		},
   189  		{
   190  			name:   "with $HELM_HOME and --home set",
   191  			args:   []string{"home", "--home", "/foo"},
   192  			envars: map[string]string{"HELM_HOME": "/bar"},
   193  			home:   "/foo",
   194  		},
   195  	}
   196  
   197  	// ensure not set locally
   198  	os.Unsetenv("HELM_HOME")
   199  
   200  	for _, tt := range tests {
   201  		t.Run(tt.name, func(t *testing.T) {
   202  			defer os.Unsetenv("HELM_HOME")
   203  
   204  			for k, v := range tt.envars {
   205  				os.Setenv(k, v)
   206  			}
   207  
   208  			cmd := newRootCmd(tt.args)
   209  			cmd.SetOutput(ioutil.Discard)
   210  			cmd.SetArgs(tt.args)
   211  			cmd.Run = func(*cobra.Command, []string) {}
   212  			if err := cmd.Execute(); err != nil {
   213  				t.Errorf("unexpected error: %s", err)
   214  			}
   215  
   216  			if settings.Home.String() != tt.home {
   217  				t.Errorf("expected home %q, got %q", tt.home, settings.Home)
   218  			}
   219  			homeFlag := cmd.Flag("home").Value.String()
   220  			homeFlag = os.ExpandEnv(homeFlag)
   221  			if homeFlag != tt.home {
   222  				t.Errorf("expected home %q, got %q", tt.home, homeFlag)
   223  			}
   224  		})
   225  	}
   226  }
   227  
   228  func resetEnv() func() {
   229  	origSettings := settings
   230  	origEnv := os.Environ()
   231  	return func() {
   232  		settings = origSettings
   233  		for _, pair := range origEnv {
   234  			kv := strings.SplitN(pair, "=", 2)
   235  			os.Setenv(kv[0], kv[1])
   236  		}
   237  	}
   238  }