diff --git a/README.md b/README.md index ad1774210..ec559873c 100644 --- a/README.md +++ b/README.md @@ -48,39 +48,7 @@ including installing pre-releases. ## Docs -- [Quick Start](docs/quickstart.md) - Read me first! -- [Installing Helm](docs/install.md) - Install Helm and Tiller - - [Kubernetes Distribution Notes](docs/kubernetes_distros.md) - - [Frequently Asked Questions](docs/install_faq.md) -- [Using Helm](docs/using_helm.md) - Learn the Helm tools - - [Plugins](docs/plugins.md) -- [Developing Charts](docs/charts.md) - An introduction to chart development - - [Chart Lifecycle Hooks](docs/charts_hooks.md) - - [Chart Tips and Tricks](docs/charts_tips_and_tricks.md) - - [Chart Repository Guide](docs/chart_repository.md) - - [Syncing your Chart Repository](docs/chart_repository_sync_example.md) - - [Signing Charts](docs/provenance.md) - - [Writing Tests for Charts](docs/chart_tests.md) -- [Chart Template Developer's Guide](docs/chart_template_guide/index.md) - Master Helm templates - - [Getting Started with Templates](docs/chart_template_guide/getting_started.md) - - [Built-in Objects](docs/chart_template_guide/builtin_objects.md) - - [Values Files](docs/chart_template_guide/values_files.md) - - [Functions and Pipelines](docs/chart_template_guide/functions_and_pipelines.md) - - [Flow Control (if/else, with, range, whitespace management)](docs/chart_template_guide/control_structures.md) - - [Variables](docs/chart_template_guide/variables.md) - - [Named Templates (Partials)](docs/chart_template_guide/named_templates.md) - - [Accessing Files Inside Templates](docs/chart_template_guide/accessing_files.md) - - [Creating a NOTES.txt File](docs/chart_template_guide/notes_files.md) - - [Subcharts and Global Values](docs/chart_template_guide/subcharts_and_globals.md) - - [Debugging Templates](docs/chart_template_guide/debugging.md) - - [Wrapping Up](docs/chart_template_guide/wrapping_up.md) - - [Appendix A: YAML Techniques](docs/chart_template_guide/yaml_techniques.md) - - [Appendix B: Go Data Types](docs/chart_template_guide/data_types.md) -- [Related Projects](docs/related.md) - More Helm tools, articles, and plugins -- [Architecture](docs/architecture.md) - Overview of the Helm/Tiller design -- [Developers](docs/developers.md) - About the developers -- [History](docs/history.md) - A brief history of the project -- [Glossary](docs/glossary.md) - Decode the Helm vocabulary +Get started with the [Quick Start guide](docs/quickstart.md) or plunge into the [complete documentation](docs/index.md) ## Roadmap diff --git a/cmd/helm/home.go b/cmd/helm/home.go index 9dfe6a373..59344f075 100644 --- a/cmd/helm/home.go +++ b/cmd/helm/home.go @@ -21,6 +21,7 @@ import ( "io" "github.com/spf13/cobra" + "k8s.io/helm/cmd/helm/helmpath" ) var longHomeHelp = ` @@ -34,7 +35,17 @@ func newHomeCmd(out io.Writer) *cobra.Command { Short: "displays the location of HELM_HOME", Long: longHomeHelp, Run: func(cmd *cobra.Command, args []string) { - fmt.Fprintf(out, homePath()+"\n") + h := helmpath.Home(homePath()) + fmt.Fprintf(out, "%s\n", h) + if flagDebug { + fmt.Fprintf(out, "Repository: %s\n", h.Repository()) + fmt.Fprintf(out, "RepositoryFile: %s\n", h.RepositoryFile()) + fmt.Fprintf(out, "Cache: %s\n", h.Cache()) + fmt.Fprintf(out, "Stable CacheIndex: %s\n", h.CacheIndex("stable")) + fmt.Fprintf(out, "Starters: %s\n", h.Starters()) + fmt.Fprintf(out, "LocalRepository: %s\n", h.LocalRepository()) + fmt.Fprintf(out, "Plugins: %s\n", h.Plugins()) + } }, } diff --git a/cmd/helm/init.go b/cmd/helm/init.go index 766cb8e62..dd6b949e3 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -228,7 +228,9 @@ func initStableRepo(cacheFile string) (*repo.Entry, error) { return nil, err } - if err := r.DownloadIndexFile(); err != nil { + // In this case, the cacheFile is always absolute. So passing empty string + // is safe. + if err := r.DownloadIndexFile(""); err != nil { return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", stableRepositoryURL, err.Error()) } diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index b349537a7..ec764ada9 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -102,7 +102,7 @@ func addRepository(name, url string, home helmpath.Home, certFile, keyFile, caFi return err } - if err := r.DownloadIndexFile(); err != nil { + if err := r.DownloadIndexFile(home.Cache()); err != nil { return fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) } diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 8dfab9a5d..8e564c98b 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -41,7 +41,7 @@ var ( ) type repoUpdateCmd struct { - update func([]*repo.ChartRepository, io.Writer) + update func([]*repo.ChartRepository, io.Writer, helmpath.Home) home helmpath.Home out io.Writer } @@ -82,11 +82,11 @@ func (u *repoUpdateCmd) run() error { repos = append(repos, r) } - u.update(repos, u.out) + u.update(repos, u.out, u.home) return nil } -func updateCharts(repos []*repo.ChartRepository, out io.Writer) { +func updateCharts(repos []*repo.ChartRepository, out io.Writer, home helmpath.Home) { fmt.Fprintln(out, "Hang tight while we grab the latest from your chart repositories...") var wg sync.WaitGroup for _, re := range repos { @@ -94,10 +94,10 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer) { go func(re *repo.ChartRepository) { defer wg.Done() if re.Config.Name == localRepository { - fmt.Fprintf(out, "...Skip %s chart repository", re.Config.Name) + fmt.Fprintf(out, "...Skip %s chart repository\n", re.Config.Name) return } - err := re.DownloadIndexFile() + err := re.DownloadIndexFile(home.Cache()) if err != nil { fmt.Fprintf(out, "...Unable to get an update from the %q chart repository (%s):\n\t%s\n", re.Config.Name, re.Config.URL, err) } else { diff --git a/cmd/helm/repo_update_test.go b/cmd/helm/repo_update_test.go index 97f023f13..e32e92fbb 100644 --- a/cmd/helm/repo_update_test.go +++ b/cmd/helm/repo_update_test.go @@ -43,7 +43,7 @@ func TestUpdateCmd(t *testing.T) { out := bytes.NewBuffer(nil) // Instead of using the HTTP updater, we provide our own for this test. // The TestUpdateCharts test verifies the HTTP behavior independently. - updater := func(repos []*repo.ChartRepository, out io.Writer) { + updater := func(repos []*repo.ChartRepository, out io.Writer, hh helmpath.Home) { for _, re := range repos { fmt.Fprintln(out, re.Config.Name) } @@ -90,7 +90,7 @@ func TestUpdateCharts(t *testing.T) { } b := bytes.NewBuffer(nil) - updateCharts([]*repo.ChartRepository{r}, b) + updateCharts([]*repo.ChartRepository{r}, b, hh) got := b.String() if strings.Contains(got, "Unable to get an update") { diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..b787463a6 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,35 @@ +# Helm Documentation + +- [Quick Start](quickstart.md) - Read me first! +- [Installing Helm](install.md) - Install Helm and Tiller + - [Kubernetes Distribution Notes](kubernetes_distros.md) + - [Frequently Asked Questions](install_faq.md) +- [Using Helm](using_helm.md) - Learn the Helm tools + - [Plugins](plugins.md) +- [Developing Charts](charts.md) - An introduction to chart development + - [Chart Lifecycle Hooks](charts_hooks.md) + - [Chart Tips and Tricks](charts_tips_and_tricks.md) + - [Chart Repository Guide](chart_repository.md) + - [Syncing your Chart Repository](chart_repository_sync_example.md) + - [Signing Charts](provenance.md) + - [Writing Tests for Charts](chart_tests.md) +- [Chart Template Developer's Guide](chart_template_guide/index.md) - Master Helm templates + - [Getting Started with Templates](chart_template_guide/getting_started.md) + - [Built-in Objects](chart_template_guide/builtin_objects.md) + - [Values Files](chart_template_guide/values_files.md) + - [Functions and Pipelines](chart_template_guide/functions_and_pipelines.md) + - [Flow Control (if/else, with, range, whitespace management)](chart_template_guide/control_structures.md) + - [Variables](chart_template_guide/variables.md) + - [Named Templates (Partials)](chart_template_guide/named_templates.md) + - [Accessing Files Inside Templates](chart_template_guide/accessing_files.md) + - [Creating a NOTES.txt File](chart_template_guide/notes_files.md) + - [Subcharts and Global Values](chart_template_guide/subcharts_and_globals.md) + - [Debugging Templates](chart_template_guide/debugging.md) + - [Wrapping Up](chart_template_guide/wrapping_up.md) + - [Appendix A: YAML Techniques](chart_template_guide/yaml_techniques.md) + - [Appendix B: Go Data Types](chart_template_guide/data_types.md) +- [Related Projects](related.md) - More Helm tools, articles, and plugins +- [Architecture](architecture.md) - Overview of the Helm/Tiller design +- [Developers](developers.md) - About the developers +- [History](history.md) - A brief history of the project +- [Glossary](glossary.md) - Decode the Helm vocabulary diff --git a/docs/related.md b/docs/related.md index 539ba80c9..8cf4a9c1b 100644 --- a/docs/related.md +++ b/docs/related.md @@ -13,6 +13,7 @@ or [pull request](https://github.com/kubernetes/helm/pulls). - [The missing CI/CD Kubernetes component: Helm package manager](https://hackernoon.com/the-missing-ci-cd-kubernetes-component-helm-package-manager-1fe002aac680#.691sk2zhu) - [CI/CD with Jenkins, Kubernetes, and Helm](https://www.youtube.com/watch?v=NVoln4HdZOY) - [The Workflow "Umbrella" Helm Chart](https://deis.com/blog/2017/workflow-chart-assembly) +- [GitLab, Consumer Driven Contracts, Helm and Kubernetes](https://medium.com/@enxebre/gitlab-consumer-driven-contracts-helm-and-kubernetes-b7235a60a1cb#.xwp1y4tgi) ## Helm Plugins diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 9a830c4d5..cc267abd1 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -30,7 +30,10 @@ import ( "github.com/Masterminds/semver" "github.com/ghodss/yaml" + // FIXME: This violates the package rules. A `cmd` should not be imported by + // something in 'pkg' "k8s.io/helm/cmd/helm/helmpath" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/repo" @@ -375,7 +378,7 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error { } wg.Add(1) go func(r *repo.ChartRepository) { - if err := r.DownloadIndexFile(); err != nil { + if err := r.DownloadIndexFile(m.HelmHome.Cache()); err != nil { fmt.Fprintf(out, "...Unable to get an update from the %q chart repository (%s):\n\t%s\n", r.Config.Name, r.Config.URL, err) } else { fmt.Fprintf(out, "...Successfully got an update from the %q chart repository\n", r.Config.Name) diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go index 6e2a3676c..4a0751f57 100644 --- a/pkg/repo/chartrepo.go +++ b/pkg/repo/chartrepo.go @@ -129,7 +129,10 @@ func (r *ChartRepository) Load() error { } // DownloadIndexFile fetches the index from a repository. -func (r *ChartRepository) DownloadIndexFile() error { +// +// cachePath is prepended to any index that does not have an absolute path. This +// is for pre-2.2.0 repo files. +func (r *ChartRepository) DownloadIndexFile(cachePath string) error { var indexURL string indexURL = strings.TrimSuffix(r.Config.URL, "/") + "/index.yaml" @@ -148,7 +151,19 @@ func (r *ChartRepository) DownloadIndexFile() error { return err } - return ioutil.WriteFile(r.Config.Cache, index, 0644) + // In Helm 2.2.0 the config.cache was accidentally switched to an absolute + // path, which broke backward compatibility. This fixes it by prepending a + // global cache path to relative paths. + // + // It is changed on DownloadIndexFile because that was the method that + // originally carried the cache path. + cp := r.Config.Cache + if !filepath.IsAbs(cp) { + cp = filepath.Join(cachePath, cp) + } + println("Writing to", cp) + + return ioutil.WriteFile(cp, index, 0644) } // Index generates an index for the chart repository and writes an index.yaml file. diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go index 2f23950f1..ccf6cfd3c 100644 --- a/pkg/repo/index_test.go +++ b/pkg/repo/index_test.go @@ -142,7 +142,7 @@ func TestDownloadIndexFile(t *testing.T) { t.Errorf("Problem creating chart repository from %s: %v", testRepo, err) } - if err := r.DownloadIndexFile(); err != nil { + if err := r.DownloadIndexFile(""); err != nil { t.Errorf("%#v", err) }