github.com/wangchanggan/helm@v0.0.0-20211020154240-11b1b7d5406d/cmd/helm/dependency_update_test.go (about) 1 /* 2 Copyright The Helm Authors. 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 }