github.com/Beeketing/helm@v2.12.1+incompatible/pkg/plugin/installer/http_installer_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 installer // import "k8s.io/helm/pkg/plugin/installer" 17 18 import ( 19 "archive/tar" 20 "bytes" 21 "compress/gzip" 22 "encoding/base64" 23 "fmt" 24 "io/ioutil" 25 "k8s.io/helm/pkg/helm/helmpath" 26 "os" 27 "path/filepath" 28 "testing" 29 ) 30 31 var _ Installer = new(HTTPInstaller) 32 33 // Fake http client 34 type TestHTTPGetter struct { 35 MockResponse *bytes.Buffer 36 MockError error 37 } 38 39 func (t *TestHTTPGetter) Get(href string) (*bytes.Buffer, error) { return t.MockResponse, t.MockError } 40 41 // Fake plugin tarball data 42 var fakePluginB64 = "H4sIAKRj51kAA+3UX0vCUBgGcC9jn+Iwuk3Peza3GeyiUlJQkcogCOzgli7dJm4TvYk+a5+k479UqquUCJ/fLs549sLO2TnvWnJa9aXnjwujYdYLovxMhsPcfnHOLdNkOXthM/IVQQYjg2yyLLJ4kXGhLp5j0z3P41tZksqxmspL3B/O+j/XtZu1y8rdYzkOZRCxduKPk53ny6Wwz/GfIIf1As8lxzGJSmoHNLJZphKHG4YpTCE0wVk3DULfpSJ3DMMqkj3P5JfMYLdX1Vr9Ie/5E5cstcdC8K04iGLX5HaJuKpWL17F0TCIBi5pf/0pjtLhun5j3f9v6r7wfnI/H0eNp9d1/5P6Gez0vzo7wsoxfrAZbTny/o9k6J8z/VkO/LPlWdC1iVpbEEcq5nmeJ13LEtmbV0k2r2PrOs9PuuNglC5rL1Y5S/syXRQmutaNw1BGnnp8Wq3UG51WvX1da3bKtZtCN/R09DwAAAAAAAAAAAAAAAAAAADAb30AoMczDwAoAAA=" 43 44 func TestStripName(t *testing.T) { 45 if stripPluginName("fake-plugin-0.0.1.tar.gz") != "fake-plugin" { 46 t.Errorf("name does not match expected value") 47 } 48 if stripPluginName("fake-plugin-0.0.1.tgz") != "fake-plugin" { 49 t.Errorf("name does not match expected value") 50 } 51 if stripPluginName("fake-plugin.tgz") != "fake-plugin" { 52 t.Errorf("name does not match expected value") 53 } 54 if stripPluginName("fake-plugin.tar.gz") != "fake-plugin" { 55 t.Errorf("name does not match expected value") 56 } 57 } 58 59 func TestHTTPInstaller(t *testing.T) { 60 source := "https://repo.localdomain/plugins/fake-plugin-0.0.1.tar.gz" 61 hh, err := ioutil.TempDir("", "helm-home-") 62 if err != nil { 63 t.Fatal(err) 64 } 65 defer os.RemoveAll(hh) 66 67 home := helmpath.Home(hh) 68 if err := os.MkdirAll(home.Plugins(), 0755); err != nil { 69 t.Fatalf("Could not create %s: %s", home.Plugins(), err) 70 } 71 72 i, err := NewForSource(source, "0.0.1", home) 73 if err != nil { 74 t.Errorf("unexpected error: %s", err) 75 } 76 77 // ensure a HTTPInstaller was returned 78 httpInstaller, ok := i.(*HTTPInstaller) 79 if !ok { 80 t.Error("expected a HTTPInstaller") 81 } 82 83 // inject fake http client responding with minimal plugin tarball 84 mockTgz, err := base64.StdEncoding.DecodeString(fakePluginB64) 85 if err != nil { 86 t.Fatalf("Could not decode fake tgz plugin: %s", err) 87 } 88 89 httpInstaller.getter = &TestHTTPGetter{ 90 MockResponse: bytes.NewBuffer(mockTgz), 91 } 92 93 // install the plugin 94 if err := Install(i); err != nil { 95 t.Error(err) 96 } 97 if i.Path() != home.Path("plugins", "fake-plugin") { 98 t.Errorf("expected path '$HELM_HOME/plugins/fake-plugin', got %q", i.Path()) 99 } 100 101 // Install again to test plugin exists error 102 if err := Install(i); err == nil { 103 t.Error("expected error for plugin exists, got none") 104 } else if err.Error() != "plugin already exists" { 105 t.Errorf("expected error for plugin exists, got (%v)", err) 106 } 107 108 } 109 110 func TestHTTPInstallerNonExistentVersion(t *testing.T) { 111 source := "https://repo.localdomain/plugins/fake-plugin-0.0.2.tar.gz" 112 hh, err := ioutil.TempDir("", "helm-home-") 113 if err != nil { 114 t.Fatal(err) 115 } 116 defer os.RemoveAll(hh) 117 118 home := helmpath.Home(hh) 119 if err := os.MkdirAll(home.Plugins(), 0755); err != nil { 120 t.Fatalf("Could not create %s: %s", home.Plugins(), err) 121 } 122 123 i, err := NewForSource(source, "0.0.2", home) 124 if err != nil { 125 t.Errorf("unexpected error: %s", err) 126 } 127 128 // ensure a HTTPInstaller was returned 129 httpInstaller, ok := i.(*HTTPInstaller) 130 if !ok { 131 t.Error("expected a HTTPInstaller") 132 } 133 134 // inject fake http client responding with error 135 httpInstaller.getter = &TestHTTPGetter{ 136 MockError: fmt.Errorf("failed to download plugin for some reason"), 137 } 138 139 // attempt to install the plugin 140 if err := Install(i); err == nil { 141 t.Error("expected error from http client") 142 } 143 144 } 145 146 func TestHTTPInstallerUpdate(t *testing.T) { 147 source := "https://repo.localdomain/plugins/fake-plugin-0.0.1.tar.gz" 148 hh, err := ioutil.TempDir("", "helm-home-") 149 if err != nil { 150 t.Fatal(err) 151 } 152 defer os.RemoveAll(hh) 153 154 home := helmpath.Home(hh) 155 if err := os.MkdirAll(home.Plugins(), 0755); err != nil { 156 t.Fatalf("Could not create %s: %s", home.Plugins(), err) 157 } 158 159 i, err := NewForSource(source, "0.0.1", home) 160 if err != nil { 161 t.Errorf("unexpected error: %s", err) 162 } 163 164 // ensure a HTTPInstaller was returned 165 httpInstaller, ok := i.(*HTTPInstaller) 166 if !ok { 167 t.Error("expected a HTTPInstaller") 168 } 169 170 // inject fake http client responding with minimal plugin tarball 171 mockTgz, err := base64.StdEncoding.DecodeString(fakePluginB64) 172 if err != nil { 173 t.Fatalf("Could not decode fake tgz plugin: %s", err) 174 } 175 176 httpInstaller.getter = &TestHTTPGetter{ 177 MockResponse: bytes.NewBuffer(mockTgz), 178 } 179 180 // install the plugin before updating 181 if err := Install(i); err != nil { 182 t.Error(err) 183 } 184 if i.Path() != home.Path("plugins", "fake-plugin") { 185 t.Errorf("expected path '$HELM_HOME/plugins/fake-plugin', got %q", i.Path()) 186 } 187 188 // Update plugin, should fail because it is not implemented 189 if err := Update(i); err == nil { 190 t.Error("update method not implemented for http installer") 191 } 192 } 193 194 func TestExtract(t *testing.T) { 195 //create a temp home 196 hh, err := ioutil.TempDir("", "helm-home-") 197 if err != nil { 198 t.Fatal(err) 199 } 200 defer os.RemoveAll(hh) 201 202 home := helmpath.Home(hh) 203 if err := os.MkdirAll(home.Plugins(), 0755); err != nil { 204 t.Fatalf("Could not create %s: %s", home.Plugins(), err) 205 } 206 207 cacheDir := filepath.Join(home.Cache(), "plugins", "plugin-key") 208 if err := os.MkdirAll(cacheDir, 0755); err != nil { 209 t.Fatalf("Could not create %s: %s", cacheDir, err) 210 } 211 212 //{"plugin.yaml", "plugin metadata up in here"}, 213 //{"README.md", "so you know what's upp"}, 214 //{"script.sh", "echo script"}, 215 216 var tarbuf bytes.Buffer 217 tw := tar.NewWriter(&tarbuf) 218 var files = []struct { 219 Name, Body string 220 }{ 221 {"../../plugin.yaml", "sneaky plugin metadata"}, 222 {"README.md", "some text"}, 223 } 224 for _, file := range files { 225 hdr := &tar.Header{ 226 Name: file.Name, 227 Typeflag: tar.TypeReg, 228 Mode: 0600, 229 Size: int64(len(file.Body)), 230 } 231 if err := tw.WriteHeader(hdr); err != nil { 232 t.Fatal(err) 233 } 234 if _, err := tw.Write([]byte(file.Body)); err != nil { 235 t.Fatal(err) 236 } 237 } 238 if err := tw.Close(); err != nil { 239 t.Fatal(err) 240 } 241 242 var buf bytes.Buffer 243 gz := gzip.NewWriter(&buf) 244 if _, err := gz.Write(tarbuf.Bytes()); err != nil { 245 t.Fatal(err) 246 } 247 gz.Close() 248 249 source := "https://repo.localdomain/plugins/fake-plugin-0.0.1.tgz" 250 extr, err := NewExtractor(source) 251 if err != nil { 252 t.Fatal(err) 253 } 254 255 if err = extr.Extract(&buf, cacheDir); err != nil { 256 t.Errorf("Did not expect error but got error: %v", err) 257 } 258 259 pluginYAMLFullPath := filepath.Join(cacheDir, "plugin.yaml") 260 if _, err := os.Stat(pluginYAMLFullPath); err != nil { 261 if os.IsNotExist(err) { 262 t.Errorf("Expected %s to exist but doesn't", pluginYAMLFullPath) 263 } else { 264 t.Error(err) 265 } 266 } 267 268 readmeFullPath := filepath.Join(cacheDir, "README.md") 269 if _, err := os.Stat(readmeFullPath); err != nil { 270 if os.IsNotExist(err) { 271 t.Errorf("Expected %s to exist but doesn't", readmeFullPath) 272 } else { 273 t.Error(err) 274 } 275 } 276 277 }