Beispiel #1
0
func TestRepoAdd(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		fmt.Fprintln(w, "OK")
	}))

	helmHome, _ = ioutil.TempDir("", "helm_home")
	defer os.Remove(helmHome)
	os.Mkdir(filepath.Join(helmHome, repositoryDir), 0755)
	os.Mkdir(cacheDirectory(), 0755)

	if err := ioutil.WriteFile(repositoriesFile(), []byte("example-repo: http://exampleurl.com"), 0666); err != nil {
		t.Errorf("%#v", err)
	}

	if err := addRepository(testName, ts.URL); err != nil {
		t.Errorf("%s", err)
	}

	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		t.Errorf("%s", err)
	}
	_, ok := f.Repositories[testName]
	if !ok {
		t.Errorf("%s was not successfully inserted into %s", testName, repositoriesFile())
	}

	if err := insertRepoLine(testName, ts.URL); err == nil {
		t.Errorf("Duplicate repository name was added")
	}

}
Beispiel #2
0
func TestRepoAdd(t *testing.T) {
	ts, thome, err := repotest.NewTempServer("testdata/testserver/*.*")
	if err != nil {
		t.Fatal(err)
	}

	oldhome := homePath()
	helmHome = thome
	hh := helmpath.Home(thome)
	defer func() {
		ts.Stop()
		helmHome = oldhome
		os.Remove(thome)
	}()
	if err := ensureTestHome(hh, t); err != nil {
		t.Fatal(err)
	}

	if err := addRepository(testName, ts.URL(), hh); err != nil {
		t.Error(err)
	}

	f, err := repo.LoadRepositoriesFile(hh.RepositoryFile())
	if err != nil {
		t.Error(err)
	}

	if !f.Has(testName) {
		t.Errorf("%s was not successfully inserted into %s", testName, hh.RepositoryFile())
	}
}
Beispiel #3
0
func fetchChart(pname string) error {

	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}

	// get download url
	u, err := mapRepoArg(pname, f.Repositories)
	if err != nil {
		return err
	}

	resp, err := http.Get(u.String())
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("Failed to fetch %s : %s", u.String(), resp.Status)
	}

	defer resp.Body.Close()
	if untarFile {
		return chartutil.Expand(untarDir, resp.Body)
	}
	p := strings.Split(u.String(), "/")
	return saveChartFile(p[len(p)-1], resp.Body)
}
Beispiel #4
0
// hasAllRepos ensures that all of the referenced deps are in the local repo cache.
func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error {
	rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile())
	if err != nil {
		return err
	}
	repos := rf.Repositories
	// Verify that all repositories referenced in the deps are actually known
	// by Helm.
	missing := []string{}
	for _, dd := range deps {
		found := false
		if dd.Repository == "" {
			found = true
		} else {
			for _, repo := range repos {
				if urlsAreEqual(repo.URL, strings.TrimSuffix(dd.Repository, "/")) {
					found = true
				}
			}
		}
		if !found {
			missing = append(missing, dd.Repository)
		}
	}
	if len(missing) > 0 {
		return fmt.Errorf("no repository definition for %s. Try 'helm repo add'", strings.Join(missing, ", "))
	}
	return nil
}
Beispiel #5
0
// getRepoNames returns the repo names of the referenced deps which can be used to fetch the cahced index file.
func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string, error) {
	rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile())
	if err != nil {
		return nil, err
	}
	repos := rf.Repositories

	reposMap := make(map[string]string)

	// Verify that all repositories referenced in the deps are actually known
	// by Helm.
	missing := []string{}
	for _, dd := range deps {
		found := false

		for _, repo := range repos {
			if urlsAreEqual(repo.URL, dd.Repository) {
				found = true
				reposMap[dd.Name] = repo.Name
				break
			}
		}
		if !found {
			missing = append(missing, dd.Repository)
		}
	}
	if len(missing) > 0 {
		return nil, fmt.Errorf("no repository definition for %s. Try 'helm repo add'", strings.Join(missing, ", "))
	}
	return reposMap, nil
}
Beispiel #6
0
// loadChartRepositories reads the repositories.yaml, and then builds a map of
// ChartRepositories.
//
// The key is the local name (which is only present in the repositories.yaml).
func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, error) {
	indices := map[string]*repo.ChartRepository{}
	repoyaml := m.HelmHome.RepositoryFile()

	// Load repositories.yaml file
	rf, err := repo.LoadRepositoriesFile(repoyaml)
	if err != nil {
		return indices, fmt.Errorf("failed to load %s: %s", repoyaml, err)
	}

	for _, re := range rf.Repositories {
		lname := re.Name
		cacheindex := m.HelmHome.CacheIndex(lname)
		index, err := repo.LoadIndexFile(cacheindex)
		if err != nil {
			return indices, err
		}

		cr := &repo.ChartRepository{
			URL:       re.URL,
			IndexFile: index,
		}
		indices[lname] = cr
	}
	return indices, nil
}
Beispiel #7
0
// ensureHome checks to see if $HELM_HOME exists
//
// If $HELM_HOME does not exist, this function will create it.
func ensureHome(home helmpath.Home, out io.Writer) error {
	configDirectories := []string{home.String(), home.Repository(), home.Cache(), home.LocalRepository()}
	for _, p := range configDirectories {
		if fi, err := os.Stat(p); err != nil {
			fmt.Fprintf(out, "Creating %s \n", p)
			if err := os.MkdirAll(p, 0755); err != nil {
				return fmt.Errorf("Could not create %s: %s", p, err)
			}
		} else if !fi.IsDir() {
			return fmt.Errorf("%s must be a directory", p)
		}
	}

	repoFile := home.RepositoryFile()
	if fi, err := os.Stat(repoFile); err != nil {
		fmt.Fprintf(out, "Creating %s \n", repoFile)
		r := repo.NewRepoFile()
		r.Add(&repo.Entry{
			Name:  stableRepository,
			URL:   stableRepositoryURL,
			Cache: "stable-index.yaml",
		}, &repo.Entry{
			Name:  localRepository,
			URL:   localRepositoryURL,
			Cache: "local-index.yaml",
		})
		if err := r.WriteFile(repoFile, 0644); err != nil {
			return err
		}
		cif := home.CacheIndex(stableRepository)
		if err := repo.DownloadIndexFile(stableRepository, stableRepositoryURL, cif); err != nil {
			fmt.Fprintf(out, "WARNING: Failed to download %s: %s (run 'helm repo update')\n", stableRepository, err)
		}
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", repoFile)
	}
	if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate {
		fmt.Fprintln(out, "Updating repository file format...")
		if err := r.WriteFile(repoFile, 0644); err != nil {
			return err
		}
	}

	localRepoIndexFile := home.LocalRepository(localRepoIndexFilePath)
	if fi, err := os.Stat(localRepoIndexFile); err != nil {
		fmt.Fprintf(out, "Creating %s \n", localRepoIndexFile)
		i := repo.NewIndexFile()
		if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {
			return err
		}

		//TODO: take this out and replace with helm update functionality
		os.Symlink(localRepoIndexFile, home.CacheIndex("local"))
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", localRepoIndexFile)
	}

	fmt.Fprintf(out, "$HELM_HOME has been configured at %s.\n", helmHome)
	return nil
}
Beispiel #8
0
// ResolveChartRef resolves a chart reference to a URL.
//
// A reference may be an HTTP URL, a 'reponame/chartname' reference, or a local path.
func (c *ChartDownloader) ResolveChartRef(ref string) (*url.URL, error) {
	// See if it's already a full URL.
	u, err := url.ParseRequestURI(ref)
	if err == nil {
		// If it has a scheme and host and path, it's a full URL
		if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 {
			return u, nil
		}
		return u, fmt.Errorf("Invalid chart url format: %s", ref)
	}

	r, err := repo.LoadRepositoriesFile(c.HelmHome.RepositoryFile())
	if err != nil {
		return u, err
	}

	// See if it's of the form: repo/path_to_chart
	p := strings.Split(ref, "/")
	if len(p) > 1 {
		if baseURL, ok := r.Repositories[p[0]]; ok {
			if !strings.HasSuffix(baseURL, "/") {
				baseURL = baseURL + "/"
			}
			return url.ParseRequestURI(baseURL + strings.Join(p[1:], "/"))
		}
		return u, fmt.Errorf("No such repo: %s", p[0])
	}
	return u, fmt.Errorf("Invalid chart url format: %s", ref)
}
Beispiel #9
0
func TestRepoRemove(t *testing.T) {
	home := createTmpHome()
	helmHome = home
	if err := ensureHome(); err != nil {
		t.Errorf("%s", err)
	}

	if err := removeRepoLine(testName); err == nil {
		t.Errorf("Expected error removing %s, but did not get one.", testName)
	}

	if err := insertRepoLine(testName, testURL); err != nil {
		t.Errorf("%s", err)
	}

	if err := removeRepoLine(testName); err != nil {
		t.Errorf("Error removing %s from repositories", testName)
	}

	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		t.Errorf("%s", err)
	}

	if _, ok := f.Repositories[testName]; ok {
		t.Errorf("%s was not successfully removed from repositories list", testName)
	}
}
Beispiel #10
0
// UpdateRepositories updates all of the local repos to the latest.
func (m *Manager) UpdateRepositories() error {
	rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile())
	if err != nil {
		return err
	}
	repos := rf.Repositories
	if len(repos) > 0 {
		// This prints warnings straight to out.
		m.parallelRepoUpdate(repos)
	}
	return nil
}
Beispiel #11
0
// ensureTestHome creates a home directory like ensureHome, but without remote references.
//
// t is used only for logging.
func ensureTestHome(home helmpath.Home, t *testing.T) error {
	configDirectories := []string{home.String(), home.Repository(), home.Cache(), home.LocalRepository(), home.Plugins(), home.Starters()}
	for _, p := range configDirectories {
		if fi, err := os.Stat(p); err != nil {
			if err := os.MkdirAll(p, 0755); err != nil {
				return fmt.Errorf("Could not create %s: %s", p, err)
			}
		} else if !fi.IsDir() {
			return fmt.Errorf("%s must be a directory", p)
		}
	}

	repoFile := home.RepositoryFile()
	if fi, err := os.Stat(repoFile); err != nil {
		rf := repo.NewRepoFile()
		rf.Add(&repo.Entry{
			Name:  "charts",
			URL:   "http://example.com/foo",
			Cache: "charts-index.yaml",
		}, &repo.Entry{
			Name:  "local",
			URL:   "http://localhost.com:7743/foo",
			Cache: "local-index.yaml",
		})
		if err := rf.WriteFile(repoFile, 0644); err != nil {
			return err
		}
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", repoFile)
	}
	if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate {
		t.Log("Updating repository file format...")
		if err := r.WriteFile(repoFile, 0644); err != nil {
			return err
		}
	}

	localRepoIndexFile := home.LocalRepository(localRepoIndexFilePath)
	if fi, err := os.Stat(localRepoIndexFile); err != nil {
		i := repo.NewIndexFile()
		if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {
			return err
		}

		//TODO: take this out and replace with helm update functionality
		os.Symlink(localRepoIndexFile, home.CacheIndex("local"))
	} else if fi.IsDir() {
		return fmt.Errorf("%s must be a file, not a directory", localRepoIndexFile)
	}

	t.Logf("$HELM_HOME has been configured at %s.\n", helmHome)
	return nil
}
Beispiel #12
0
func (u *repoUpdateCmd) run() error {
	f, err := repo.LoadRepositoriesFile(u.home.RepositoryFile())
	if err != nil {
		return err
	}

	if len(f.Repositories) == 0 {
		return errors.New("no repositories found. You must add one before updating")
	}

	u.update(f.Repositories, flagDebug, u.out, u.home)
	return nil
}
Beispiel #13
0
func runUpdate(cmd *cobra.Command, args []string) error {

	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}

	if len(f.Repositories) == 0 {
		return errors.New("no repositories found. You must add one before updating")
	}

	updateCharts(f.Repositories, verboseUpdate)
	return nil
}
Beispiel #14
0
// ResolveChartVersion resolves a chart reference to a URL.
//
// A reference may be an HTTP URL, a 'reponame/chartname' reference, or a local path.
//
// A version is a SemVer string (1.2.3-beta.1+f334a6789).
//
// 	- For fully qualified URLs, the version will be ignored (since URLs aren't versioned)
//	- For a chart reference
//		* If version is non-empty, this will return the URL for that version
//		* If version is empty, this will return the URL for the latest version
// 		* If no version can be found, an error is returned
func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, error) {
	// See if it's already a full URL.
	// FIXME: Why do we use url.ParseRequestURI instead of url.Parse?
	u, err := url.ParseRequestURI(ref)
	if err == nil {
		// If it has a scheme and host and path, it's a full URL
		if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 {
			return u, nil
		}
		return u, fmt.Errorf("invalid chart url format: %s", ref)
	}

	r, err := repo.LoadRepositoriesFile(c.HelmHome.RepositoryFile())
	if err != nil {
		return u, err
	}

	// See if it's of the form: repo/path_to_chart
	p := strings.SplitN(ref, "/", 2)
	if len(p) < 2 {
		return u, fmt.Errorf("invalid chart url format: %s", ref)
	}

	repoName := p[0]
	chartName := p[1]
	rf, err := findRepoEntry(repoName, r.Repositories)
	if err != nil {
		return u, err
	}
	if rf.URL == "" {
		return u, fmt.Errorf("no URL found for repository %q", repoName)
	}

	// Next, we need to load the index, and actually look up the chart.
	i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(repoName))
	if err != nil {
		return u, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err)
	}

	cv, err := i.Get(chartName, version)
	if err != nil {
		return u, fmt.Errorf("chart %q not found in %s index. (try 'helm repo update'). %s", chartName, repoName, err)
	}

	if len(cv.URLs) == 0 {
		return u, fmt.Errorf("chart %q has no downloadable URLs", ref)
	}
	return url.Parse(cv.URLs[0])
}
Beispiel #15
0
func updateRepoLine(name, url string, home helmpath.Home) error {
	cif := home.CacheIndex(name)
	f, err := repo.LoadRepositoriesFile(home.RepositoryFile())
	if err != nil {
		return err
	}

	f.Update(&repo.Entry{
		Name:  name,
		URL:   url,
		Cache: filepath.Base(cif),
	})

	return f.WriteFile(home.RepositoryFile(), 0666)
}
Beispiel #16
0
func runRepoList(cmd *cobra.Command, args []string) error {
	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}
	if len(f.Repositories) == 0 {
		return errors.New("no repositories to show")
	}
	table := uitable.New()
	table.MaxColWidth = 50
	table.AddRow("NAME", "URL")
	for k, v := range f.Repositories {
		table.AddRow(k, v)
	}
	fmt.Println(table)
	return nil
}
Beispiel #17
0
func insertRepoLine(name, url string, home helmpath.Home) error {
	cif := home.CacheIndex(name)
	f, err := repo.LoadRepositoriesFile(home.RepositoryFile())
	if err != nil {
		return err
	}

	if f.Has(name) {
		return fmt.Errorf("The repository name you provided (%s) already exists. Please specify a different name.", name)
	}
	f.Add(&repo.Entry{
		Name:  name,
		URL:   url,
		Cache: filepath.Base(cif),
	})
	return f.WriteFile(home.RepositoryFile(), 0644)
}
Beispiel #18
0
func (a *repoListCmd) run() error {
	f, err := repo.LoadRepositoriesFile(a.home.RepositoryFile())
	if err != nil {
		return err
	}
	if len(f.Repositories) == 0 {
		return errors.New("no repositories to show")
	}
	table := uitable.New()
	table.MaxColWidth = 50
	table.AddRow("NAME", "URL")
	for _, re := range f.Repositories {
		table.AddRow(re.Name, re.URL)
	}
	fmt.Fprintln(a.out, table)
	return nil
}
Beispiel #19
0
func (a *repoListCmd) run() error {
	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}
	if len(f.Repositories) == 0 {
		return errors.New("no repositories to show")
	}
	table := uitable.New()
	table.MaxColWidth = 50
	table.AddRow("NAME", "URL")
	for k, v := range f.Repositories {
		table.AddRow(k, v)
	}
	fmt.Println(table)
	return nil
}
Beispiel #20
0
func insertRepoLine(name, url string) error {
	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}
	_, ok := f.Repositories[name]
	if ok {
		return fmt.Errorf("The repository name you provided (%s) already exists. Please specify a different name.", name)
	}

	if f.Repositories == nil {
		f.Repositories = make(map[string]string)
	}

	f.Repositories[name] = url

	b, _ := yaml.Marshal(&f.Repositories)
	return ioutil.WriteFile(repositoriesFile(), b, 0666)
}
Beispiel #21
0
func TestRepoRemove(t *testing.T) {
	testURL := "https://test-url.com"

	b := bytes.NewBuffer(nil)

	home, err := tempHelmHome(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(home)
	hh := helmpath.Home(home)

	if err := removeRepoLine(b, testName, hh); err == nil {
		t.Errorf("Expected error removing %s, but did not get one.", testName)
	}
	if err := insertRepoLine(testName, testURL, hh); err != nil {
		t.Error(err)
	}

	mf, _ := os.Create(hh.CacheIndex(testName))
	mf.Close()

	b.Reset()
	if err := removeRepoLine(b, testName, hh); err != nil {
		t.Errorf("Error removing %s from repositories", testName)
	}
	if !strings.Contains(b.String(), "has been removed") {
		t.Errorf("Unexpected output: %s", b.String())
	}

	if _, err := os.Stat(hh.CacheIndex(testName)); err == nil {
		t.Errorf("Error cache file was not removed for repository %s", testName)
	}

	f, err := repo.LoadRepositoriesFile(hh.RepositoryFile())
	if err != nil {
		t.Error(err)
	}

	if f.Has(testName) {
		t.Errorf("%s was not successfully removed from repositories list", testName)
	}
}
Beispiel #22
0
func (s *searchCmd) buildIndex() (*search.Index, error) {
	// Load the repositories.yaml
	rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile())
	if err != nil {
		return nil, err
	}

	i := search.NewIndex()
	for n := range rf.Repositories {
		f := s.helmhome.CacheIndex(n)
		ind, err := repo.LoadIndexFile(f)
		if err != nil {
			fmt.Fprintf(s.out, "WARNING: Repo %q is corrupt. Try 'helm update': %s", f, err)
			continue
		}

		i.AddRepo(n, ind)
	}
	return i, nil
}
Beispiel #23
0
func (s *searchCmd) buildIndex() (*search.Index, error) {
	// Load the repositories.yaml
	rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile())
	if err != nil {
		return nil, err
	}

	i := search.NewIndex()
	for _, re := range rf.Repositories {
		n := re.Name
		f := s.helmhome.CacheIndex(n)
		ind, err := repo.LoadIndexFile(f)
		if err != nil {
			fmt.Fprintf(s.out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n)
			continue
		}

		i.AddRepo(n, ind, s.versions)
	}
	return i, nil
}
Beispiel #24
0
func removeRepoLine(out io.Writer, name string, home helmpath.Home) error {
	repoFile := home.RepositoryFile()
	r, err := repo.LoadRepositoriesFile(repoFile)
	if err != nil {
		return err
	}

	if !r.Remove(name) {
		return fmt.Errorf("no repo named %q found", name)
	}
	if err := r.WriteFile(repoFile, 0644); err != nil {
		return err
	}

	if err := removeRepoCache(name, home); err != nil {
		return err
	}

	fmt.Fprintf(out, "%q has been removed from your repositories\n", name)

	return nil
}
Beispiel #25
0
func removeRepoLine(name string) error {
	r, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		return err
	}

	_, ok := r.Repositories[name]
	if ok {
		delete(r.Repositories, name)
		b, err := yaml.Marshal(&r.Repositories)
		if err != nil {
			return err
		}
		if err := ioutil.WriteFile(repositoriesFile(), b, 0666); err != nil {
			return err
		}

	} else {
		return fmt.Errorf("The repository, %s, does not exist in your repositories list", name)
	}

	return nil
}
Beispiel #26
0
func TestRepoRemove(t *testing.T) {
	testURL := "https://test-url.com"
	home := createTmpHome()
	helmHome = home
	if err := ensureHome(); err != nil {
		t.Errorf("%s", err)
	}

	if err := removeRepoLine(testName); err == nil {
		t.Errorf("Expected error removing %s, but did not get one.", testName)
	}

	if err := insertRepoLine(testName, testURL); err != nil {
		t.Errorf("%s", err)
	}

	mf, _ := os.Create(cacheIndexFile(testName))
	mf.Close()

	if err := removeRepoLine(testName); err != nil {
		t.Errorf("Error removing %s from repositories", testName)
	}

	if _, err := os.Stat(cacheIndexFile(testName)); err == nil {
		t.Errorf("Error cache file was not removed for repository %s", testName)
	}

	f, err := repo.LoadRepositoriesFile(repositoriesFile())
	if err != nil {
		t.Errorf("%s", err)
	}

	if _, ok := f.Repositories[testName]; ok {
		t.Errorf("%s was not successfully removed from repositories list", testName)
	}
}