github.com/y-taka-23/helm@v2.8.0+incompatible/cmd/helm/dependency_update_test.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package main
    17  
    18  import (
    19  	"bytes"
    20  	"io/ioutil"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/ghodss/yaml"
    27  
    28  	"k8s.io/helm/pkg/chartutil"
    29  	"k8s.io/helm/pkg/helm/helmpath"
    30  	"k8s.io/helm/pkg/proto/hapi/chart"
    31  	"k8s.io/helm/pkg/provenance"
    32  	"k8s.io/helm/pkg/repo"
    33  	"k8s.io/helm/pkg/repo/repotest"
    34  )
    35  
    36  func TestDependencyUpdateCmd(t *testing.T) {
    37  	hh, err := tempHelmHome(t)
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	cleanup := resetEnv()
    42  	defer func() {
    43  		os.RemoveAll(hh.String())
    44  		cleanup()
    45  	}()
    46  
    47  	settings.Home = hh
    48  
    49  	srv := repotest.NewServer(hh.String())
    50  	defer srv.Stop()
    51  	copied, err := srv.CopyCharts("testdata/testcharts/*.tgz")
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  	t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
    56  	t.Logf("Listening on directory %s", srv.Root())
    57  
    58  	chartname := "depup"
    59  	if err := createTestingChart(hh.String(), chartname, srv.URL()); err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	out := bytes.NewBuffer(nil)
    64  	duc := &dependencyUpdateCmd{out: out}
    65  	duc.helmhome = helmpath.Home(hh)
    66  	duc.chartpath = filepath.Join(hh.String(), chartname)
    67  
    68  	if err := duc.run(); err != nil {
    69  		output := out.String()
    70  		t.Logf("Output: %s", output)
    71  		t.Fatal(err)
    72  	}
    73  
    74  	output := out.String()
    75  	// This is written directly to stdout, so we have to capture as is.
    76  	if !strings.Contains(output, `update from the "test" chart repository`) {
    77  		t.Errorf("Repo did not get updated\n%s", output)
    78  	}
    79  
    80  	// Make sure the actual file got downloaded.
    81  	expect := filepath.Join(hh.String(), chartname, "charts/reqtest-0.1.0.tgz")
    82  	if _, err := os.Stat(expect); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	hash, err := provenance.DigestFile(expect)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	i, err := repo.LoadIndexFile(duc.helmhome.CacheIndex("test"))
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  
    96  	reqver := i.Entries["reqtest"][0]
    97  	if h := reqver.Digest; h != hash {
    98  		t.Errorf("Failed hash match: expected %s, got %s", hash, h)
    99  	}
   100  
   101  	// Now change the dependencies and update. This verifies that on update,
   102  	// old dependencies are cleansed and new dependencies are added.
   103  	reqfile := &chartutil.Requirements{
   104  		Dependencies: []*chartutil.Dependency{
   105  			{Name: "reqtest", Version: "0.1.0", Repository: srv.URL()},
   106  			{Name: "compressedchart", Version: "0.3.0", Repository: srv.URL()},
   107  		},
   108  	}
   109  	dir := filepath.Join(hh.String(), chartname)
   110  	if err := writeRequirements(dir, reqfile); err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	if err := duc.run(); err != nil {
   114  		output := out.String()
   115  		t.Logf("Output: %s", output)
   116  		t.Fatal(err)
   117  	}
   118  
   119  	// In this second run, we should see compressedchart-0.3.0.tgz, and not
   120  	// the 0.1.0 version.
   121  	expect = filepath.Join(hh.String(), chartname, "charts/compressedchart-0.3.0.tgz")
   122  	if _, err := os.Stat(expect); err != nil {
   123  		t.Fatalf("Expected %q: %s", expect, err)
   124  	}
   125  	dontExpect := filepath.Join(hh.String(), chartname, "charts/compressedchart-0.1.0.tgz")
   126  	if _, err := os.Stat(dontExpect); err == nil {
   127  		t.Fatalf("Unexpected %q", dontExpect)
   128  	}
   129  }
   130  
   131  func TestDependencyUpdateCmd_SkipRefresh(t *testing.T) {
   132  	hh, err := tempHelmHome(t)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	cleanup := resetEnv()
   137  	defer func() {
   138  		os.RemoveAll(hh.String())
   139  		cleanup()
   140  	}()
   141  
   142  	settings.Home = hh
   143  
   144  	srv := repotest.NewServer(hh.String())
   145  	defer srv.Stop()
   146  	copied, err := srv.CopyCharts("testdata/testcharts/*.tgz")
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
   151  	t.Logf("Listening on directory %s", srv.Root())
   152  
   153  	chartname := "depup"
   154  	if err := createTestingChart(hh.String(), chartname, srv.URL()); err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	out := bytes.NewBuffer(nil)
   159  	duc := &dependencyUpdateCmd{out: out}
   160  	duc.helmhome = helmpath.Home(hh)
   161  	duc.chartpath = filepath.Join(hh.String(), chartname)
   162  	duc.skipRefresh = true
   163  
   164  	if err := duc.run(); err == nil {
   165  		t.Fatal("Expected failure to find the repo with skipRefresh")
   166  	}
   167  
   168  	output := out.String()
   169  	// This is written directly to stdout, so we have to capture as is.
   170  	if strings.Contains(output, `update from the "test" chart repository`) {
   171  		t.Errorf("Repo was unexpectedly updated\n%s", output)
   172  	}
   173  }
   174  
   175  func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
   176  	hh, err := tempHelmHome(t)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	cleanup := resetEnv()
   181  	defer func() {
   182  		os.RemoveAll(hh.String())
   183  		cleanup()
   184  	}()
   185  
   186  	settings.Home = hh
   187  
   188  	srv := repotest.NewServer(hh.String())
   189  	defer srv.Stop()
   190  	copied, err := srv.CopyCharts("testdata/testcharts/*.tgz")
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
   195  	t.Logf("Listening on directory %s", srv.Root())
   196  
   197  	chartname := "depupdelete"
   198  	if err := createTestingChart(hh.String(), chartname, srv.URL()); err != nil {
   199  		t.Fatal(err)
   200  	}
   201  
   202  	out := bytes.NewBuffer(nil)
   203  	duc := &dependencyUpdateCmd{out: out}
   204  	duc.helmhome = helmpath.Home(hh)
   205  	duc.chartpath = filepath.Join(hh.String(), chartname)
   206  
   207  	if err := duc.run(); err != nil {
   208  		output := out.String()
   209  		t.Logf("Output: %s", output)
   210  		t.Fatal(err)
   211  	}
   212  
   213  	// Chart repo is down
   214  	srv.Stop()
   215  
   216  	if err := duc.run(); err == nil {
   217  		output := out.String()
   218  		t.Logf("Output: %s", output)
   219  		t.Fatal("Expected error, got nil")
   220  	}
   221  
   222  	// Make sure charts dir still has dependencies
   223  	files, err := ioutil.ReadDir(filepath.Join(duc.chartpath, "charts"))
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	dependencies := []string{"compressedchart-0.1.0.tgz", "reqtest-0.1.0.tgz"}
   228  
   229  	if len(dependencies) != len(files) {
   230  		t.Fatalf("Expected %d chart dependencies, got %d", len(dependencies), len(files))
   231  	}
   232  	for index, file := range files {
   233  		if dependencies[index] != file.Name() {
   234  			t.Fatalf("Chart dependency %s not matching %s", dependencies[index], file.Name())
   235  		}
   236  	}
   237  
   238  	// Make sure tmpcharts is deleted
   239  	if _, err := os.Stat(filepath.Join(duc.chartpath, "tmpcharts")); !os.IsNotExist(err) {
   240  		t.Fatalf("tmpcharts dir still exists")
   241  	}
   242  }
   243  
   244  // createTestingChart creates a basic chart that depends on reqtest-0.1.0
   245  //
   246  // The baseURL can be used to point to a particular repository server.
   247  func createTestingChart(dest, name, baseURL string) error {
   248  	cfile := &chart.Metadata{
   249  		Name:    name,
   250  		Version: "1.2.3",
   251  	}
   252  	dir := filepath.Join(dest, name)
   253  	_, err := chartutil.Create(cfile, dest)
   254  	if err != nil {
   255  		return err
   256  	}
   257  	req := &chartutil.Requirements{
   258  		Dependencies: []*chartutil.Dependency{
   259  			{Name: "reqtest", Version: "0.1.0", Repository: baseURL},
   260  			{Name: "compressedchart", Version: "0.1.0", Repository: baseURL},
   261  		},
   262  	}
   263  	return writeRequirements(dir, req)
   264  }
   265  
   266  func writeRequirements(dir string, req *chartutil.Requirements) error {
   267  	data, err := yaml.Marshal(req)
   268  	if err != nil {
   269  		return err
   270  	}
   271  
   272  	return ioutil.WriteFile(filepath.Join(dir, "requirements.yaml"), data, 0655)
   273  }