github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/cmd/helm/repo_add_test.go (about)

     1  /*
     2  Copyright The Helm Authors.
     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  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  
    28  	"sigs.k8s.io/yaml"
    29  
    30  	"github.com/stefanmcshane/helm/internal/test/ensure"
    31  	"github.com/stefanmcshane/helm/pkg/helmpath"
    32  	"github.com/stefanmcshane/helm/pkg/helmpath/xdg"
    33  	"github.com/stefanmcshane/helm/pkg/repo"
    34  	"github.com/stefanmcshane/helm/pkg/repo/repotest"
    35  )
    36  
    37  func TestRepoAddCmd(t *testing.T) {
    38  	srv, err := repotest.NewTempServerWithCleanup(t, "testdata/testserver/*.*")
    39  	if err != nil {
    40  		t.Fatal(err)
    41  	}
    42  	defer srv.Stop()
    43  
    44  	// A second test server is setup to verify URL changing
    45  	srv2, err := repotest.NewTempServerWithCleanup(t, "testdata/testserver/*.*")
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	defer srv2.Stop()
    50  
    51  	tmpdir := filepath.Join(ensure.TempDir(t), "path-component.yaml/data")
    52  	err = os.MkdirAll(tmpdir, 0777)
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	repoFile := filepath.Join(tmpdir, "repositories.yaml")
    57  
    58  	tests := []cmdTestCase{
    59  		{
    60  			name:   "add a repository",
    61  			cmd:    fmt.Sprintf("repo add test-name %s --repository-config %s --repository-cache %s", srv.URL(), repoFile, tmpdir),
    62  			golden: "output/repo-add.txt",
    63  		},
    64  		{
    65  			name:   "add repository second time",
    66  			cmd:    fmt.Sprintf("repo add test-name %s --repository-config %s --repository-cache %s", srv.URL(), repoFile, tmpdir),
    67  			golden: "output/repo-add2.txt",
    68  		},
    69  		{
    70  			name:      "add repository different url",
    71  			cmd:       fmt.Sprintf("repo add test-name %s --repository-config %s --repository-cache %s", srv2.URL(), repoFile, tmpdir),
    72  			wantError: true,
    73  		},
    74  		{
    75  			name:   "add repository second time",
    76  			cmd:    fmt.Sprintf("repo add test-name %s --repository-config %s --repository-cache %s --force-update", srv2.URL(), repoFile, tmpdir),
    77  			golden: "output/repo-add.txt",
    78  		},
    79  	}
    80  
    81  	runTestCmd(t, tests)
    82  }
    83  
    84  func TestRepoAdd(t *testing.T) {
    85  	ts, err := repotest.NewTempServerWithCleanup(t, "testdata/testserver/*.*")
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	defer ts.Stop()
    90  
    91  	rootDir := ensure.TempDir(t)
    92  	repoFile := filepath.Join(rootDir, "repositories.yaml")
    93  
    94  	const testRepoName = "test-name"
    95  
    96  	o := &repoAddOptions{
    97  		name:               testRepoName,
    98  		url:                ts.URL(),
    99  		forceUpdate:        false,
   100  		deprecatedNoUpdate: true,
   101  		repoFile:           repoFile,
   102  	}
   103  	os.Setenv(xdg.CacheHomeEnvVar, rootDir)
   104  
   105  	if err := o.run(ioutil.Discard); err != nil {
   106  		t.Error(err)
   107  	}
   108  
   109  	f, err := repo.LoadFile(repoFile)
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  
   114  	if !f.Has(testRepoName) {
   115  		t.Errorf("%s was not successfully inserted into %s", testRepoName, repoFile)
   116  	}
   117  
   118  	idx := filepath.Join(helmpath.CachePath("repository"), helmpath.CacheIndexFile(testRepoName))
   119  	if _, err := os.Stat(idx); os.IsNotExist(err) {
   120  		t.Errorf("Error cache index file was not created for repository %s", testRepoName)
   121  	}
   122  	idx = filepath.Join(helmpath.CachePath("repository"), helmpath.CacheChartsFile(testRepoName))
   123  	if _, err := os.Stat(idx); os.IsNotExist(err) {
   124  		t.Errorf("Error cache charts file was not created for repository %s", testRepoName)
   125  	}
   126  
   127  	o.forceUpdate = true
   128  
   129  	if err := o.run(ioutil.Discard); err != nil {
   130  		t.Errorf("Repository was not updated: %s", err)
   131  	}
   132  
   133  	if err := o.run(ioutil.Discard); err != nil {
   134  		t.Errorf("Duplicate repository name was added")
   135  	}
   136  }
   137  
   138  func TestRepoAddCheckLegalName(t *testing.T) {
   139  	ts, err := repotest.NewTempServerWithCleanup(t, "testdata/testserver/*.*")
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  	defer ts.Stop()
   144  	defer resetEnv()()
   145  
   146  	const testRepoName = "test-hub/test-name"
   147  
   148  	rootDir := ensure.TempDir(t)
   149  	repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml")
   150  
   151  	o := &repoAddOptions{
   152  		name:               testRepoName,
   153  		url:                ts.URL(),
   154  		forceUpdate:        false,
   155  		deprecatedNoUpdate: true,
   156  		repoFile:           repoFile,
   157  	}
   158  	os.Setenv(xdg.CacheHomeEnvVar, rootDir)
   159  
   160  	wantErrorMsg := fmt.Sprintf("repository name (%s) contains '/', please specify a different name without '/'", testRepoName)
   161  
   162  	if err := o.run(ioutil.Discard); err != nil {
   163  		if wantErrorMsg != err.Error() {
   164  			t.Fatalf("Actual error %s, not equal to expected error %s", err, wantErrorMsg)
   165  		}
   166  	} else {
   167  		t.Fatalf("expect reported an error.")
   168  	}
   169  }
   170  
   171  func TestRepoAddConcurrentGoRoutines(t *testing.T) {
   172  	const testName = "test-name"
   173  	repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml")
   174  	repoAddConcurrent(t, testName, repoFile)
   175  }
   176  
   177  func TestRepoAddConcurrentDirNotExist(t *testing.T) {
   178  	const testName = "test-name-2"
   179  	repoFile := filepath.Join(ensure.TempDir(t), "foo", "repositories.yaml")
   180  	repoAddConcurrent(t, testName, repoFile)
   181  }
   182  
   183  func TestRepoAddConcurrentNoFileExtension(t *testing.T) {
   184  	const testName = "test-name-3"
   185  	repoFile := filepath.Join(ensure.TempDir(t), "repositories")
   186  	repoAddConcurrent(t, testName, repoFile)
   187  }
   188  
   189  func TestRepoAddConcurrentHiddenFile(t *testing.T) {
   190  	const testName = "test-name-4"
   191  	repoFile := filepath.Join(ensure.TempDir(t), ".repositories")
   192  	repoAddConcurrent(t, testName, repoFile)
   193  }
   194  
   195  func repoAddConcurrent(t *testing.T, testName, repoFile string) {
   196  	ts, err := repotest.NewTempServerWithCleanup(t, "testdata/testserver/*.*")
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  	defer ts.Stop()
   201  
   202  	var wg sync.WaitGroup
   203  	wg.Add(3)
   204  	for i := 0; i < 3; i++ {
   205  		go func(name string) {
   206  			defer wg.Done()
   207  			o := &repoAddOptions{
   208  				name:               name,
   209  				url:                ts.URL(),
   210  				deprecatedNoUpdate: true,
   211  				forceUpdate:        false,
   212  				repoFile:           repoFile,
   213  			}
   214  			if err := o.run(ioutil.Discard); err != nil {
   215  				t.Error(err)
   216  			}
   217  		}(fmt.Sprintf("%s-%d", testName, i))
   218  	}
   219  	wg.Wait()
   220  
   221  	b, err := ioutil.ReadFile(repoFile)
   222  	if err != nil {
   223  		t.Error(err)
   224  	}
   225  
   226  	var f repo.File
   227  	if err := yaml.Unmarshal(b, &f); err != nil {
   228  		t.Error(err)
   229  	}
   230  
   231  	var name string
   232  	for i := 0; i < 3; i++ {
   233  		name = fmt.Sprintf("%s-%d", testName, i)
   234  		if !f.Has(name) {
   235  			t.Errorf("%s was not successfully inserted into %s: %s", name, repoFile, f.Repositories[0])
   236  		}
   237  	}
   238  }
   239  
   240  func TestRepoAddFileCompletion(t *testing.T) {
   241  	checkFileCompletion(t, "repo add", false)
   242  	checkFileCompletion(t, "repo add reponame", false)
   243  	checkFileCompletion(t, "repo add reponame https://example.com", false)
   244  }
   245  
   246  func TestRepoAddWithPasswordFromStdin(t *testing.T) {
   247  	srv := repotest.NewTempServerWithCleanupAndBasicAuth(t, "testdata/testserver/*.*")
   248  	defer srv.Stop()
   249  
   250  	defer resetEnv()()
   251  
   252  	in, err := os.Open("testdata/password")
   253  	if err != nil {
   254  		t.Errorf("unexpected error, got '%v'", err)
   255  	}
   256  
   257  	tmpdir := ensure.TempDir(t)
   258  	repoFile := filepath.Join(tmpdir, "repositories.yaml")
   259  
   260  	store := storageFixture()
   261  
   262  	const testName = "test-name"
   263  	const username = "username"
   264  	cmd := fmt.Sprintf("repo add %s %s --repository-config %s --repository-cache %s --username %s --password-stdin", testName, srv.URL(), repoFile, tmpdir, username)
   265  	var result string
   266  	_, result, err = executeActionCommandStdinC(store, in, cmd)
   267  	if err != nil {
   268  		t.Errorf("unexpected error, got '%v'", err)
   269  	}
   270  
   271  	if !strings.Contains(result, fmt.Sprintf("\"%s\" has been added to your repositories", testName)) {
   272  		t.Errorf("Repo was not successfully added. Output: %s", result)
   273  	}
   274  }