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  }