Merge branch 'master' into use-versioned-objects-in-installer

pull/2524/head
Adam Reese 8 years ago committed by GitHub
commit f1a072fd32

@ -33,9 +33,9 @@ Think of it like apt/yum/homebrew for Kubernetes.
Binary downloads of the Helm client can be found at the following links:
- [OSX](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.1-darwin-amd64.tar.gz)
- [Linux](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.1-linux-amd64.tar.gz)
- [Linux 32-bit](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.1-linux-386.tar.gz)
- [OSX](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.2-darwin-amd64.tar.gz)
- [Linux](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.2-linux-amd64.tar.gz)
- [Linux 32-bit](https://kubernetes-helm.storage.googleapis.com/helm-v2.4.2-linux-386.tar.gz)
Unpack the `helm` binary and add it to your PATH and you are good to go!
macOS/[homebrew](https://brew.sh/) users can also use `brew install kubernetes-helm`.

@ -3,7 +3,7 @@ machine:
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
environment:
GOVERSION: "1.8.1"
GOVERSION: "1.8.3"
GOPATH: "${HOME}/.go_workspace"
WORKDIR: "${GOPATH}/src/k8s.io/helm"
PROJECT_NAME: "kubernetes-helm"

@ -87,7 +87,7 @@ func TestCreateStarterCmd(t *testing.T) {
if err != nil {
t.Fatal(err)
}
old := helmpath.Home(environment.DefaultHelmHome())
old := helmpath.Home(environment.DefaultHelmHome)
settings.Home = thome
defer func() {
settings.Home = old

@ -52,12 +52,12 @@ func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "delete [flags] RELEASE_NAME [...]",
Aliases: []string{"del"},
SuggestFor: []string{"remove", "rm"},
Short: "given a release name, delete the release from Kubernetes",
Long: deleteDesc,
PersistentPreRunE: setupConnection,
Use: "delete [flags] RELEASE_NAME [...]",
Aliases: []string{"del"},
SuggestFor: []string{"remove", "rm"},
Short: "given a release name, delete the release from Kubernetes",
Long: deleteDesc,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("command 'delete' requires a release name")

@ -34,7 +34,7 @@ func TestFetchCmd(t *testing.T) {
if err != nil {
t.Fatal(err)
}
old := helmpath.Home(environment.DefaultHelmHome())
old := helmpath.Home(environment.DefaultHelmHome)
settings.Home = hh
defer func() {
settings.Home = old

@ -54,10 +54,10 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "get [flags] RELEASE_NAME",
Short: "download a named release",
Long: getHelp,
PersistentPreRunE: setupConnection,
Use: "get [flags] RELEASE_NAME",
Short: "download a named release",
Long: getHelp,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errReleaseRequired

@ -19,7 +19,6 @@ package main // import "k8s.io/helm/cmd/helm"
import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"os"
@ -40,23 +39,16 @@ import (
"k8s.io/helm/pkg/tlsutil"
)
const (
localRepoIndexFilePath = "index.yaml"
)
var (
tlsCaCertFile string // path to TLS CA certificate file
tlsCertFile string // path to TLS certificate file
tlsKeyFile string // path to TLS key file
tlsVerify bool // enable TLS and verify remote certificates
tlsEnable bool // enable TLS
)
var (
kubeContext string
settings helm_env.EnvSettings
// TODO refactor out this global var
kubeContext string
tillerTunnel *kube.Tunnel
settings helm_env.EnvSettings
)
var globalUsage = `The Kubernetes package manager
@ -83,34 +75,58 @@ Environment:
$KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config")
`
func newRootCmd(out io.Writer) *cobra.Command {
func setFlagFromEnv(name, envar string, cmd *cobra.Command) {
if cmd.Flags().Changed(name) {
return
}
if v, ok := os.LookupEnv(envar); ok {
cmd.Flags().Set(name, v)
}
}
func setFlagsFromEnv(flags map[string]string, cmd *cobra.Command) {
for name, envar := range flags {
setFlagFromEnv(name, envar, cmd)
}
}
func addRootFlags(cmd *cobra.Command) {
pf := cmd.PersistentFlags()
pf.StringVar((*string)(&settings.Home), "home", helm_env.DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
pf.StringVar(&settings.TillerHost, "host", "", "address of tiller. Overrides $HELM_HOST")
pf.StringVar(&kubeContext, "kube-context", "", "name of the kubeconfig context to use")
pf.BoolVar(&settings.Debug, "debug", false, "enable verbose output")
pf.StringVar(&settings.TillerNamespace, "tiller-namespace", tiller_env.DefaultTillerNamespace, "namespace of tiller")
}
func initRootFlags(cmd *cobra.Command) {
setFlagsFromEnv(map[string]string{
"debug": helm_env.DebugEnvVar,
"home": helm_env.HomeEnvVar,
"host": helm_env.HostEnvVar,
"tiller-namespace": tiller_env.TillerNamespaceEnvVar,
}, cmd.Root())
tlsCaCertFile = os.ExpandEnv(tlsCaCertFile)
tlsCertFile = os.ExpandEnv(tlsCertFile)
tlsKeyFile = os.ExpandEnv(tlsKeyFile)
}
func newRootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "helm",
Short: "The Helm package manager for Kubernetes.",
Long: globalUsage,
SilenceUsage: true,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
tlsCaCertFile = os.ExpandEnv(tlsCaCertFile)
tlsCertFile = os.ExpandEnv(tlsCertFile)
tlsKeyFile = os.ExpandEnv(tlsKeyFile)
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
initRootFlags(cmd)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
PersistentPostRun: func(*cobra.Command, []string) {
teardown()
},
}
p := cmd.PersistentFlags()
p.StringVar((*string)(&settings.Home), "home", helm_env.DefaultHelmHome(), "location of your Helm config. Overrides $HELM_HOME")
p.StringVar(&settings.TillerHost, "host", helm_env.DefaultHelmHost(), "address of tiller. Overrides $HELM_HOST")
p.StringVar(&kubeContext, "kube-context", "", "name of the kubeconfig context to use")
p.BoolVar(&settings.Debug, "debug", false, "enable verbose output")
p.StringVar(&settings.TillerNamespace, "tiller-namespace", tiller_env.GetTillerNamespace(), "namespace of tiller")
if os.Getenv(helm_env.PluginDisableEnvVar) != "1" {
settings.PlugDirs = os.Getenv(helm_env.PluginEnvVar)
if settings.PlugDirs == "" {
settings.PlugDirs = settings.Home.Plugins()
}
}
addRootFlags(cmd)
out := cmd.OutOrStdout()
cmd.AddCommand(
// chart commands
@ -163,7 +179,7 @@ func init() {
}
func main() {
cmd := newRootCmd(os.Stdout)
cmd := newRootCmd()
if err := cmd.Execute(); err != nil {
os.Exit(1)
}

@ -23,6 +23,7 @@ import (
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"regexp"
"sync"
"testing"
@ -321,7 +322,7 @@ func ensureTestHome(home helmpath.Home, t *testing.T) error {
}
}
localRepoIndexFile := home.LocalRepository(localRepoIndexFilePath)
localRepoIndexFile := home.LocalRepository(localRepositoryIndexFile)
if fi, err := os.Stat(localRepoIndexFile); err != nil {
i := repo.NewIndexFile()
if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {
@ -337,3 +338,79 @@ func ensureTestHome(home helmpath.Home, t *testing.T) error {
t.Logf("$HELM_HOME has been configured at %s.\n", settings.Home.String())
return nil
}
func TestRootCmd(t *testing.T) {
oldhome := os.Getenv("HELM_HOME")
defer os.Setenv("HELM_HOME", oldhome)
tests := []struct {
name string
args []string
envars map[string]string
home string
}{
{
name: "defaults",
args: []string{"home"},
home: filepath.Join(os.Getenv("HOME"), "/.helm"),
},
{
name: "with --home set",
args: []string{"--home", "/foo"},
home: "/foo",
},
{
name: "subcommands with --home set",
args: []string{"home", "--home", "/foo"},
home: "/foo",
},
{
name: "with $HELM_HOME set",
args: []string{"home"},
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "subcommands with $HELM_HOME set",
args: []string{"home"},
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "with $HELM_HOME and --home set",
args: []string{"home", "--home", "/foo"},
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/foo",
},
}
// ensure not set locally
os.Unsetenv("HELM_HOME")
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer os.Unsetenv("HELM_HOME")
for k, v := range tt.envars {
os.Setenv(k, v)
}
cmd := newRootCmd()
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tt.args)
cmd.Run = func(*cobra.Command, []string) {}
if err := cmd.Execute(); err != nil {
t.Errorf("unexpected error: %s", err)
}
if settings.Home.String() != tt.home {
t.Errorf("expected home %q, got %q", tt.home, settings.Home)
}
homeFlag := cmd.Flag("home").Value.String()
homeFlag = os.ExpandEnv(homeFlag)
if homeFlag != tt.home {
t.Errorf("expected home %q, got %q", tt.home, homeFlag)
}
})
}
}

@ -56,11 +56,11 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command {
his := &historyCmd{out: w, helmc: c}
cmd := &cobra.Command{
Use: "history [flags] RELEASE_NAME",
Long: historyHelp,
Short: "fetch release history",
Aliases: []string{"hist"},
PersistentPreRunE: setupConnection,
Use: "history [flags] RELEASE_NAME",
Long: historyHelp,
Short: "fetch release history",
Aliases: []string{"hist"},
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
switch {
case len(args) == 0:

@ -35,7 +35,7 @@ func newHomeCmd(out io.Writer) *cobra.Command {
Long: longHomeHelp,
Run: func(cmd *cobra.Command, args []string) {
h := settings.Home
fmt.Fprintf(out, "%s\n", h)
fmt.Fprintln(out, h)
if settings.Debug {
fmt.Fprintf(out, "Repository: %s\n", h.Repository())
fmt.Fprintf(out, "RepositoryFile: %s\n", h.RepositoryFile())
@ -47,6 +47,5 @@ func newHomeCmd(out io.Writer) *cobra.Command {
}
},
}
return cmd
}

@ -54,8 +54,9 @@ To dump a manifest containing the Tiller deployment YAML, combine the
`
const (
stableRepository = "stable"
localRepository = "local"
stableRepository = "stable"
localRepository = "local"
localRepositoryIndexFile = "index.yaml"
)
var (
@ -296,7 +297,7 @@ func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) err
if err != nil {
return err
}
lr, err := initLocalRepo(home.LocalRepository(localRepoIndexFilePath), home.CacheIndex("local"))
lr, err := initLocalRepo(home.LocalRepository(localRepositoryIndexFile), home.CacheIndex("local"))
if err != nil {
return err
}

@ -214,7 +214,7 @@ func TestEnsureHome(t *testing.T) {
t.Errorf("%s should not be a directory", fi)
}
if fi, err := os.Stat(hh.LocalRepository(localRepoIndexFilePath)); err != nil {
if fi, err := os.Stat(hh.LocalRepository(localRepositoryIndexFile)); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)

@ -148,10 +148,10 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "install [CHART]",
Short: "install a chart archive",
Long: installDesc,
PersistentPreRunE: setupConnection,
Use: "install [CHART]",
Short: "install a chart archive",
Long: installDesc,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "chart name"); err != nil {
return err

@ -166,6 +166,9 @@ func generateDeployment(opts *Options) *v1beta1.Deployment {
},
},
HostNetwork: opts.EnableHostNetwork,
NodeSelector: map[string]string{
"beta.kubernetes.io/os": "linux",
},
},
},
},

@ -82,11 +82,11 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "list [flags] [FILTER]",
Short: "list releases",
Long: listHelp,
Aliases: []string{"ls"},
PersistentPreRunE: setupConnection,
Use: "list [flags] [FILTER]",
Short: "list releases",
Long: listHelp,
Aliases: []string{"ls"},
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
list.filter = strings.Join(args, " ")

@ -25,19 +25,10 @@ import (
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm/helmpath"
helm_env "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/plugin"
)
const pluginEnvVar = "HELM_PLUGIN"
func pluginDirs(home helmpath.Home) string {
if dirs := os.Getenv(pluginEnvVar); dirs != "" {
return dirs
}
return home.Plugins()
}
// loadPlugins loads plugins into the command list.
//
// This follows a different pattern than the other commands because it has
@ -46,16 +37,25 @@ func pluginDirs(home helmpath.Home) string {
func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
// If HELM_NO_PLUGINS is set to 1, do not load plugins.
if settings.PlugDirs == "" {
if os.Getenv(helm_env.PluginDisableEnvVar) == "1" {
return
}
found, err := findPlugins(settings.PlugDirs)
found, err := findPlugins(settings.PluginDirs())
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load plugins: %s", err)
return
}
processParent := func(cmd *cobra.Command, args []string) ([]string, error) {
k, u := manuallyProcessArgs(args)
if err := cmd.Parent().ParseFlags(k); err != nil {
return nil, err
}
initRootFlags(cmd)
return u, nil
}
// Now we create commands for all of these.
for _, plug := range found {
plug := plug
@ -69,9 +69,8 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
Short: md.Usage,
Long: md.Description,
RunE: func(cmd *cobra.Command, args []string) error {
k, u := manuallyProcessArgs(args)
if err := cmd.Parent().ParseFlags(k); err != nil {
u, err := processParent(cmd, args)
if err != nil {
return err
}
@ -99,10 +98,9 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
}
if md.UseTunnel {
c.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
c.PreRunE = func(cmd *cobra.Command, args []string) error {
// Parse the parent flag, but not the local flags.
k, _ := manuallyProcessArgs(args)
if err := c.Parent().ParseFlags(k); err != nil {
if _, err := processParent(cmd, args); err != nil {
return err
}
return setupConnection(cmd, args)

@ -30,6 +30,8 @@ import (
"golang.org/x/crypto/ssh/terminal"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/provenance"
@ -48,13 +50,14 @@ Versioned chart archives are used by Helm package repositories.
`
type packageCmd struct {
save bool
sign bool
path string
key string
keyring string
version string
destination string
save bool
sign bool
path string
key string
keyring string
version string
destination string
dependencyUpdate bool
out io.Writer
home helmpath.Home
@ -99,6 +102,7 @@ func newPackageCmd(out io.Writer) *cobra.Command {
f.StringVar(&pkg.keyring, "keyring", defaultKeyring(), "location of a public keyring")
f.StringVar(&pkg.version, "version", "", "set the version on the chart to this semver version")
f.StringVarP(&pkg.destination, "destination", "d", ".", "location to write the chart.")
f.BoolVarP(&pkg.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`)
return cmd
}
@ -109,6 +113,21 @@ func (p *packageCmd) run(cmd *cobra.Command, args []string) error {
return err
}
if p.dependencyUpdate {
downloadManager := &downloader.Manager{
Out: p.out,
ChartPath: path,
HelmHome: settings.Home,
Keyring: p.keyring,
Getters: getter.All(settings),
Debug: settings.Debug,
}
if err := downloadManager.Update(); err != nil {
return err
}
}
ch, err := chartutil.LoadDir(path)
if err != nil {
return err

@ -44,11 +44,8 @@ func newPluginListCmd(out io.Writer) *cobra.Command {
}
func (pcmd *pluginListCmd) run() error {
plugdirs := pluginDirs(pcmd.home)
debug("pluginDirs: %s", plugdirs)
plugins, err := findPlugins(plugdirs)
debug("pluginDirs: %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
if err != nil {
return err
}

@ -59,9 +59,8 @@ func (pcmd *pluginRemoveCmd) complete(args []string) error {
}
func (pcmd *pluginRemoveCmd) run() error {
plugdirs := pluginDirs(pcmd.home)
debug("loading installed plugins from %s", plugdirs)
plugins, err := findPlugins(plugdirs)
debug("loading installed plugins from %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
if err != nil {
return err
}

@ -23,6 +23,7 @@ import (
"strings"
"testing"
helm_env "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/plugin"
@ -71,7 +72,6 @@ func TestLoadPlugins(t *testing.T) {
settings.Home = old
}()
hh := settings.Home
settings.PlugDirs = hh.Plugins()
out := bytes.NewBuffer(nil)
cmd := &cobra.Command{}
@ -139,12 +139,11 @@ func TestLoadPlugins(t *testing.T) {
func TestLoadPlugins_HelmNoPlugins(t *testing.T) {
// Set helm home to point to testdata
old := settings.Home
oldPlugDirs := settings.PlugDirs
settings.Home = "testdata/helmhome"
settings.PlugDirs = ""
os.Setenv(helm_env.PluginDisableEnvVar, "1")
defer func() {
settings.Home = old
settings.PlugDirs = oldPlugDirs
os.Unsetenv(helm_env.PluginDisableEnvVar)
}()
out := bytes.NewBuffer(nil)
@ -161,7 +160,6 @@ func TestSetupEnv(t *testing.T) {
name := "pequod"
settings.Home = helmpath.Home("testdata/helmhome")
base := filepath.Join(settings.Home.Plugins(), name)
settings.PlugDirs = settings.Home.Plugins()
settings.Debug = true
defer func() {
settings.Debug = false

@ -61,9 +61,8 @@ func (pcmd *pluginUpdateCmd) complete(args []string) error {
func (pcmd *pluginUpdateCmd) run() error {
installer.Debug = settings.Debug
plugdirs := pluginDirs(pcmd.home)
debug("loading installed plugins from %s", plugdirs)
plugins, err := findPlugins(plugdirs)
debug("loading installed plugins from %s", settings.PluginDirs())
plugins, err := findPlugins(settings.PluginDirs())
if err != nil {
return err
}

@ -48,10 +48,10 @@ func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "test [RELEASE]",
Short: "test a release",
Long: releaseTestDesc,
PersistentPreRunE: setupConnection,
Use: "test [RELEASE]",
Short: "test a release",
Long: releaseTestDesc,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "release name"); err != nil {
return err

@ -55,7 +55,7 @@ func newRepoUpdateCmd(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Aliases: []string{"up"},
Short: "update information on available charts in the chart repositories",
Short: "update information of available charts locally from chart repositories",
Long: updateDesc,
RunE: func(cmd *cobra.Command, args []string) error {
u.home = settings.Home

@ -57,7 +57,7 @@ func newResetCmd(client helm.Interface, out io.Writer) *cobra.Command {
Use: "reset",
Short: "uninstalls Tiller from a cluster",
Long: resetDesc,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
PreRunE: func(cmd *cobra.Command, args []string) error {
if err := setupConnection(cmd, args); !d.force && err != nil {
return err
}

@ -30,7 +30,7 @@ const rollbackDesc = `
This command rolls back a release to a previous revision.
The first argument of the rollback command is the name of a release, and the
second is a revision (version) number. To see revision numbers, run
second is a revision (version) number. To see revision numbers, run
'helm history RELEASE'.
`
@ -54,10 +54,10 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "rollback [flags] [RELEASE] [REVISION]",
Short: "roll back a release to a previous revision",
Long: rollbackDesc,
PersistentPreRunE: setupConnection,
Use: "rollback [flags] [RELEASE] [REVISION]",
Short: "roll back a release to a previous revision",
Long: rollbackDesc,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "release name", "revision number"); err != nil {
return err

@ -57,10 +57,10 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "status [flags] RELEASE_NAME",
Short: "displays the status of the named release",
Long: statusHelp,
PersistentPreRunE: setupConnection,
Use: "status [flags] RELEASE_NAME",
Short: "displays the status of the named release",
Long: statusHelp,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errReleaseRequired

@ -91,10 +91,10 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
}
cmd := &cobra.Command{
Use: "upgrade [RELEASE] [CHART]",
Short: "upgrade a release",
Long: upgradeDesc,
PersistentPreRunE: setupConnection,
Use: "upgrade [RELEASE] [CHART]",
Short: "upgrade a release",
Long: upgradeDesc,
PreRunE: setupConnection,
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "release name", "chart path"); err != nil {
return err

@ -10,6 +10,8 @@ send us a pull request.
**Q: Why do I get a `unsupported protocol scheme ""` error when trying to fetch a chart from my custom repo?**
A: This is likely caused by you creating your chart repo index without specifying the `--url` flag.
A: (Helm < 2.5.0) This is likely caused by you creating your chart repo index without specifying the `--url` flag.
Try recreating your `index.yaml` file with a command like `heml repo index --url http://my-repo/charts .`,
and then re-uploading it to your custom charts repo.
This behavior was changed in Helm 2.5.0.

@ -170,87 +170,6 @@ metadata:
Now `{{ .Chart.Name }}` resolves to `mychart`, and `{{ .Chart.Version }}` resolves to `0.1.0`.
## Creating override-able sections with `block`
Say we want to create a template in our `_helpers.tpl` file, but then override part of its behavior in our template. This is what blocks are for. Sometimes we don't want to just insert a template with `template`, but we want to sketch out a default and let another template override our default. This makes it possible for one chart to define a base template, but allow another chart to strategically override some of its behavior.
Blocks are declared like this:
```yaml
{{ block "NAME" PIPELINE }}
{{ end }}
```
Here, "NAME" is the name that a `define` block can use to override it, and PIPELINE is the pipeline that will set the scope. So let's rewrite our `labels:` section to use this strategy. We'll create a basic labels section in our `_helpers.tpl` file, but add some extra labels in the `configmap.yaml` template.
Let's start with `_helpers.tpl`:
```yaml
{{- define "my_labels" }}
labels:
chart: {{ .Chart.Name }}
version: {{ .Chart.Version }}
{{ block "my_extra_labels" . }}extras: false{{ end }}
{{- end }}
```
Inside of our `my_labels` template, we now declare a block called `my_extra_labels`. By default, this section will have one extra label: `extras: false`. If we were to execute this using the same `configmap.yaml` file from last time, we'd get this:
```yaml
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: tinseled-womba-configmap
labels:
chart: mychart
version: 0.1.0
extras: false
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
```
But inside of our `configmap.yaml` template, we can override `my_extra_labels`:
```yaml
{{- define "my_extra_labels" }}chart: {{ .Chart.Name }}{{ end -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "my_labels" . }}
data:
myvalue: "Hello World"
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end }}
```
On the first line, we redefine `my_extra_labels` to include `chart: {{ .Chart.Name }}`. If we
run this, we will get:
```yaml
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ignorant-scorp-configmap
labels:
chart: mychart
version: 0.1.0
chart: mychart
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
```
Gone is the `extras: false` section, since that part of the template is now overridden by our new template, which placed `chart: mychart` into the output.
Blocks are not frequently used in Helm charts. But they do provide one mechanism for creating "abstract" charts, and then selectively overriding parts of the abstract template with concrete implementations.
## The `include` function
Say we've defined a simple template that looks like this:

@ -175,57 +175,33 @@ Globals are useful for passing information like this, though it does take some p
## Sharing Templates with Subcharts
Parent charts and subcharts can share templates. This can become very powerful when coupled with `block`s. For example, we can define a `block` in the `subchart` ConfigMap like this:
Parent charts and subcharts can share templates. Any defined block in any chart is
available to other charts.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
{{block "labels" . }}from: mysubchart{{ end }}
data:
dessert: {{ .Values.dessert }}
salad: {{ .Values.global.salad }}
```
Running this would produce:
```yaml
# Source: mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gaudy-mastiff-cfgmap2
from: mysubchart
data:
dessert: ice cream
salad: caesar
```
Note that the `from:` line says `mysubchart`. In a previous section, we created `mychart/templates/_helpers.tpl`. Let's define a new named template there called `labels` to match the declaration on the block above.
For example, we can define a simple template like this:
```yaml
{{- define "labels" }}from: mychart{{ end }}
```
Recall how the labels on templates are _globally shared_. That means that if we create a block named `labels` in one chart, and then define an override named `labels` in another chart, the override will be applied.
Recall how the labels on templates are _globally shared_. Thus, the `labels` chart
can be included from any other chart.
Now if we do a `helm install --dry-run --debug mychart`, it will override the block:
While chart developers have a choice between `include` and `template`, one advantage
of using `include` is that `include` can dynamically reference templates:
```yaml
# Source: mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nasal-cheetah-cfgmap2
from: mychart
data:
dessert: ice cream
salad: caesar
{{ include $mytemplate }}
```
Now `from:` is set to `mychart` because the block was overridden.
The above will dereference `$mytemplate`. The `template` function, in contrast,
will only accept a string literal.
## Avoid Using Blocks
Using this method, you can write flexible "base" charts that can be added as subcharts to many different charts, and which will support selective overriding using blocks.
The Go template language provides a `block` keyword that allows developers to provide
a default implementation which is overridden later. In Helm charts, blocks are not
the best tool for overriding because it if multiple implementations of the same block
are provided, the one selected is unpredictable.
This section of the guide has focused on subcharts. We've seen how to inherit values, how to use global values, and how to override templates with blocks. In the next section we will turn to debugging, and learn how to catch errors in templates.
The suggestion is to instead use `include`.

@ -1,6 +1,6 @@
# Chart Tests
A chart contains a number of Kubernetes resources and components that work together. As a chart author, you may want to write some tests that validate that your charts works as expected when it is installed. These tests also help the chart consumer understand what your chart is supposed to do.
A chart contains a number of Kubernetes resources and components that work together. As a chart author, you may want to write some tests that validate that your chart works as expected when it is installed. These tests also help the chart consumer understand what your chart is supposed to do.
A **test** in a helm chart lives under the `templates/` directory and is a pod definition that specifies a container with a given command to run. The container should exit successfully (exit 0) for a test to be considered a success. The pod definiton must contain one of the helm test hook annotations: `helm.sh/hooks: test-success` or `helm.sh/hooks: test-failure`.
@ -17,12 +17,12 @@ You can run the pre-defined tests in Helm on a release using the command `helm t
In Helm, there are two test hooks: `test-success` and `test-failure`
`test-success` indiciates that test pod should complete successfully. In other words, the containers in the pod should exit 0.
`test-failure` is a way to assert that a test pod should not complete successfully. If the containers in the pod do not exit 0, that indiciates success.
`test-success` indicates that test pod should complete successfully. In other words, the containers in the pod should exit 0.
`test-failure` is a way to assert that a test pod should not complete successfully. If the containers in the pod do not exit 0, that indicates success.
## Example Test
Here is an example of a helm test pod definition in an example maraidb chart:
Here is an example of a helm test pod definition in an example mariadb chart:
```
mariadb/

@ -234,11 +234,11 @@ team.
In addition to the other fields above, each requirements entry may contain
the optional field `alias`.
Adding an alias for a dependency chart would add another copy
of the chart as a new depdendency using alias as name of new dependency.
Adding an alias for a dependency chart would put
a chart in dependencies using alias as name of new dependency.
One can use `alias` in cases where they need multiple copies of same chart
as dependencies all independent of one another.
One can use `alias` in cases where they need to access a chart
with other name(s).
````
# parentchart/requirements.yaml
@ -246,16 +246,21 @@ dependencies:
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias:
- one-more-subchart
- another-subchart
alias: new-subchart-1
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias: new-subchart-2
- name: subchart
repository: http://localhost:10191
version: 0.1.0
````
In the above example we will get 3 depenendencies in all for `parentchart`
```
subchart
one-more-subchart
another-subchart
new-subchart-1
new-subchart-2
```
Manual way of achieving this is copy/pasting same chart in

@ -78,7 +78,7 @@ Go provides a way for setting template options to control behavior
when a map is indexed with a key that's not present in the map. This
is typically set with template.Options("missingkey=option"), where option
can be default, zero, or error. While setting this option to error will
stop execution with an arror, this would apply to every missing key in the
stop execution with an error, this would apply to every missing key in the
map. There may be situations where a chart developer wants to enforce this
behavior for select values in the values.yml file.

@ -1,4 +1,4 @@
#Alpine: A simple Helm chart
# Alpine: A simple Helm chart
Run a single pod of Alpine Linux.

@ -33,7 +33,7 @@ Environment:
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -66,4 +66,4 @@ Environment:
* [helm verify](helm_verify.md) - verify that a chart at the given path has been signed and is valid
* [helm version](helm_version.md) - print the client/server version information
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -25,7 +25,7 @@ helm completion SHELL
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -34,4 +34,4 @@ helm completion SHELL
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -44,7 +44,7 @@ helm create NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -53,4 +53,4 @@ helm create NAME
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -35,7 +35,7 @@ helm delete [flags] RELEASE_NAME [...]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -44,4 +44,4 @@ helm delete [flags] RELEASE_NAME [...]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -58,7 +58,7 @@ for this case.
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -70,4 +70,4 @@ for this case.
* [helm dependency list](helm_dependency_list.md) - list the dependencies for the given chart
* [helm dependency update](helm_dependency_update.md) - update charts/ based on the contents of requirements.yaml
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -31,7 +31,7 @@ helm dependency build [flags] CHART
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -40,4 +40,4 @@ helm dependency build [flags] CHART
### SEE ALSO
* [helm dependency](helm_dependency.md) - manage a chart's dependencies
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -23,7 +23,7 @@ helm dependency list [flags] CHART
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -32,4 +32,4 @@ helm dependency list [flags] CHART
### SEE ALSO
* [helm dependency](helm_dependency.md) - manage a chart's dependencies
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -36,7 +36,7 @@ helm dependency update [flags] CHART
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -45,4 +45,4 @@ helm dependency update [flags] CHART
### SEE ALSO
* [helm dependency](helm_dependency.md) - manage a chart's dependencies
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -45,7 +45,7 @@ helm fetch [flags] [chart URL | repo/chartname] [...]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -54,4 +54,4 @@ helm fetch [flags] [chart URL | repo/chartname] [...]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -37,7 +37,7 @@ helm get [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -49,4 +49,4 @@ helm get [flags] RELEASE_NAME
* [helm get manifest](helm_get_manifest.md) - download the manifest for a named release
* [helm get values](helm_get_values.md) - download the values file for a named release
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -25,7 +25,7 @@ helm get hooks [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -34,4 +34,4 @@ helm get hooks [flags] RELEASE_NAME
### SEE ALSO
* [helm get](helm_get.md) - download a named release
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -27,7 +27,7 @@ helm get manifest [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -36,4 +36,4 @@ helm get manifest [flags] RELEASE_NAME
### SEE ALSO
* [helm get](helm_get.md) - download a named release
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -24,7 +24,7 @@ helm get values [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -33,4 +33,4 @@ helm get values [flags] RELEASE_NAME
### SEE ALSO
* [helm get](helm_get.md) - download a named release
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -40,7 +40,7 @@ helm history [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -49,4 +49,4 @@ helm history [flags] RELEASE_NAME
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -18,7 +18,7 @@ helm home
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -27,4 +27,4 @@ helm home
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -54,7 +54,7 @@ helm init
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -63,4 +63,4 @@ helm init
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -32,7 +32,7 @@ helm inspect [CHART]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -43,4 +43,4 @@ helm inspect [CHART]
* [helm inspect chart](helm_inspect_chart.md) - shows inspect chart
* [helm inspect values](helm_inspect_values.md) - shows inspect values
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -30,7 +30,7 @@ helm inspect chart [CHART]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -39,4 +39,4 @@ helm inspect chart [CHART]
### SEE ALSO
* [helm inspect](helm_inspect.md) - inspect a chart
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -30,7 +30,7 @@ helm inspect values [CHART]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -39,4 +39,4 @@ helm inspect values [CHART]
### SEE ALSO
* [helm inspect](helm_inspect.md) - inspect a chart
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -97,7 +97,7 @@ helm install [CHART]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -106,4 +106,4 @@ helm install [CHART]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -28,7 +28,7 @@ helm lint [flags] PATH
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -37,4 +37,4 @@ helm lint [flags] PATH
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -61,7 +61,7 @@ helm list [flags] [FILTER]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -70,4 +70,4 @@ helm list [flags] [FILTER]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -23,6 +23,7 @@ helm package [flags] [CHART_PATH] [...]
### Options
```
-u, --dependency-update update dependencies from "requirements.yaml" to dir "charts/" before packaging
-d, --destination string location to write the chart. (default ".")
--key string name of the key to use when signing. Used if --sign is true
--keyring string location of a public keyring (default "~/.gnupg/pubring.gpg")
@ -35,7 +36,7 @@ helm package [flags] [CHART_PATH] [...]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -44,4 +45,4 @@ helm package [flags] [CHART_PATH] [...]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 5-Jun-2017

@ -13,7 +13,7 @@ Manage client-side Helm plugins.
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -26,4 +26,4 @@ Manage client-side Helm plugins.
* [helm plugin remove](helm_plugin_remove.md) - remove one or more Helm plugins
* [helm plugin update](helm_plugin_update.md) - update one or more Helm plugins
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -21,7 +21,7 @@ helm plugin install [options] <path|url>...
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -30,4 +30,4 @@ helm plugin install [options] <path|url>...
### SEE ALSO
* [helm plugin](helm_plugin.md) - add, list, or remove Helm plugins
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -15,7 +15,7 @@ helm plugin list
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -24,4 +24,4 @@ helm plugin list
### SEE ALSO
* [helm plugin](helm_plugin.md) - add, list, or remove Helm plugins
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -15,7 +15,7 @@ helm plugin remove <plugin>...
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -24,4 +24,4 @@ helm plugin remove <plugin>...
### SEE ALSO
* [helm plugin](helm_plugin.md) - add, list, or remove Helm plugins
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -15,7 +15,7 @@ helm plugin update <plugin>...
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -24,4 +24,4 @@ helm plugin update <plugin>...
### SEE ALSO
* [helm plugin](helm_plugin.md) - add, list, or remove Helm plugins
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -17,7 +17,7 @@ Example usage:
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -29,6 +29,6 @@ Example usage:
* [helm repo index](helm_repo_index.md) - generate an index file given a directory containing packaged charts
* [helm repo list](helm_repo_list.md) - list chart repositories
* [helm repo remove](helm_repo_remove.md) - remove a chart repository
* [helm repo update](helm_repo_update.md) - update information on available charts in the chart repositories
* [helm repo update](helm_repo_update.md) - update information of available charts locally from chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -24,7 +24,7 @@ helm repo add [flags] [NAME] [URL]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -33,4 +33,4 @@ helm repo add [flags] [NAME] [URL]
### SEE ALSO
* [helm repo](helm_repo.md) - add, list, remove, update, and index chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -31,7 +31,7 @@ helm repo index [flags] [DIR]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -40,4 +40,4 @@ helm repo index [flags] [DIR]
### SEE ALSO
* [helm repo](helm_repo.md) - add, list, remove, update, and index chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -15,7 +15,7 @@ helm repo list [flags]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -24,4 +24,4 @@ helm repo list [flags]
### SEE ALSO
* [helm repo](helm_repo.md) - add, list, remove, update, and index chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -15,7 +15,7 @@ helm repo remove [flags] [NAME]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -24,4 +24,4 @@ helm repo remove [flags] [NAME]
### SEE ALSO
* [helm repo](helm_repo.md) - add, list, remove, update, and index chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -1,6 +1,6 @@
## helm repo update
update information on available charts in the chart repositories
update information of available charts locally from chart repositories
### Synopsis
@ -21,7 +21,7 @@ helm repo update
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -30,4 +30,4 @@ helm repo update
### SEE ALSO
* [helm repo](helm_repo.md) - add, list, remove, update, and index chart repositories
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -31,7 +31,7 @@ helm reset
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -40,4 +40,4 @@ helm reset
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -9,7 +9,7 @@ roll back a release to a previous revision
This command rolls back a release to a previous revision.
The first argument of the rollback command is the name of a release, and the
second is a revision (version) number. To see revision numbers, run
second is a revision (version) number. To see revision numbers, run
'helm history RELEASE'.
@ -37,7 +37,7 @@ helm rollback [flags] [RELEASE] [REVISION]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -46,4 +46,4 @@ helm rollback [flags] [RELEASE] [REVISION]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -28,7 +28,7 @@ helm search [keyword]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -37,4 +37,4 @@ helm search [keyword]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -36,7 +36,7 @@ helm serve
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -45,4 +45,4 @@ helm serve
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -35,7 +35,7 @@ helm status [flags] RELEASE_NAME
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -44,4 +44,4 @@ helm status [flags] RELEASE_NAME
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -32,7 +32,7 @@ helm test [RELEASE]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -41,4 +41,4 @@ helm test [RELEASE]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -67,7 +67,7 @@ helm upgrade [RELEASE] [CHART]
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -76,4 +76,4 @@ helm upgrade [RELEASE] [CHART]
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -30,7 +30,7 @@ helm verify [flags] PATH
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -39,4 +39,4 @@ helm verify [flags] PATH
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -44,7 +44,7 @@ helm version
```
--debug enable verbose output
--home string location of your Helm config. Overrides $HELM_HOME (default "~/.helm")
--home string location of your Helm config. Overrides $HELM_HOME (default "$HOME/.helm")
--host string address of tiller. Overrides $HELM_HOST
--kube-context string name of the kubeconfig context to use
--tiller-namespace string namespace of tiller (default "kube-system")
@ -53,4 +53,4 @@ helm version
### SEE ALSO
* [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 26-May-2017
###### Auto generated by spf13/cobra on 29-May-2017

@ -5,7 +5,7 @@
.SH NAME
.PP
helm\-repo\-update \- update information on available charts in the chart repositories
helm\-repo\-update \- update information of available charts locally from chart repositories
.SH SYNOPSIS

@ -54,6 +54,7 @@ Tools layered on top of Helm or Tiller.
- [Cog](https://github.com/ohaiwalt/cog-helm) - Helm chart to deploy Cog on Kubernetes
- [Monocular](https://github.com/helm/monocular) - Web UI for Helm Chart repositories
- [Helm Chart Publisher](https://github.com/luizbafilho/helm-chart-publisher) - HTTP API for publishing Helm Charts in an easy way
- [Armada](https://github.com/att-comdev/armada) - Manage prefixed releases throughout various Kubernetes namespaces, and removes completed jobs for complex deployments. Used by the [Openstack-Helm](https://github.com/openstack/openstack-helm) team.
## Helm Included

@ -215,12 +215,13 @@ You can then override any of these settings in a YAML formatted file,
and then pass that file during installation.
```console
$ echo 'mariadbUser: user0' > config.yaml
$ echo '{mariadbUser: user0, mariadbDatabase: user0db}' > config.yaml
$ helm install -f config.yaml stable/mariadb
```
The above will set the default MariaDB user to `user0`, but accept all
the rest of the defaults for that chart.
The above will create a default MariaDB user with the name `user0`, and
grant this user access to a newly created `user0db` database, but will
accept all the rest of the defaults for that chart.
There are two ways to pass configuration data during install:
@ -355,7 +356,7 @@ is not a full list of cli flags. To see a description of all flags, just run
This defaults to 300 (5 minutes)
- `--wait`: Waits until all Pods are in a ready state, PVCs are bound, Deployments
have minimum (`Desired` minus `maxUnavailable`) Pods in ready state and
Services have and IP address (and Ingress if a `LoadBalancer`) before
Services have an IP address (and Ingress if a `LoadBalancer`) before
marking the release as successful. It will wait for as long as the
`--timeout` value. If timeout is reached, the release will be marked as
`FAILED`.
@ -473,6 +474,15 @@ Note: The `stable` repository is managed on the [Kubernetes Charts
GitHub repository](https://github.com/kubernetes/charts). That project
accepts chart source code, and (after audit) packages those for you.
## Tiller, Namespaces and RBAC
In some cases you may wish to scope Tiller or deploy multiple Tillers to a single cluster. Here are some best practices when operating in those circumstances.
1. Tiller can be [installed](install.md) into any namespace. By default, it is installed into kube-system. You can run multiple Tillers provided they each run in their own namespace.
2. Limiting Tiller to only be able to install into specific namespaces and/or resource types is controlled by Kubernetes [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/) roles and rolebindings.
3. Release names are unique PER TILLER INSTANCE.
4. Charts should only contain resources that exist in a single namespace.
5. It is not recommended to have multiple Tillers configured to manage resources in the same namespace.
## Conclusion
This chapter has covered the basic usage patterns of the `helm` client,

@ -66,7 +66,7 @@ type Dependency struct {
// string or pair of child/parent sublist items.
ImportValues []interface{} `json:"import-values"`
// Alias usable alias to be used for the chart
Alias []string `json:"alias"`
Alias string `json:"alias"`
}
// ErrNoRequirementsFile to detect error condition
@ -218,7 +218,7 @@ func ProcessRequirementsTags(reqs *Requirements, cvals Values) {
}
func copyChartAsAlias(charts []*chart.Chart, dependentChart, aliasChart string) *chart.Chart {
func getAliasDependency(charts []*chart.Chart, aliasChart *Dependency) *chart.Chart {
var chartFound chart.Chart
for _, existingChart := range charts {
if existingChart == nil {
@ -227,13 +227,17 @@ func copyChartAsAlias(charts []*chart.Chart, dependentChart, aliasChart string)
if existingChart.Metadata == nil {
continue
}
if existingChart.Metadata.Name != dependentChart {
if existingChart.Metadata.Name != aliasChart.Name {
continue
}
if existingChart.Metadata.Version != aliasChart.Version {
continue
}
chartFound = *existingChart
newMetadata := *existingChart.Metadata
newMetadata.Name = aliasChart
if aliasChart.Alias != "" {
newMetadata.Name = aliasChart.Alias
}
chartFound.Metadata = &newMetadata
return &chartFound
}
@ -253,19 +257,16 @@ func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error {
return nil
}
var chartDependencies []*chart.Chart
for _, req := range reqs.Dependencies {
for _, alias := range req.Alias {
aliasDependency := copyChartAsAlias(c.Dependencies, req.Name, alias)
if aliasDependency == nil {
break
}
c.Dependencies = append(c.Dependencies, aliasDependency)
origReqName := req.Name
req.Name = alias
reqs.Dependencies = append(reqs.Dependencies, req)
req.Name = origReqName
if chartDependency := getAliasDependency(c.Dependencies, req); chartDependency != nil {
chartDependencies = append(chartDependencies, chartDependency)
}
if req.Alias != "" {
req.Name = req.Alias
}
}
c.Dependencies = chartDependencies
// set all to true
for _, lr := range reqs.Dependencies {
@ -361,22 +362,17 @@ func getParents(c *chart.Chart, out []*chart.Chart) []*chart.Chart {
}
// processImportValues merges values from child to parent based on the chart's dependencies' ImportValues field.
func processImportValues(c *chart.Chart, v *chart.Config) error {
func processImportValues(c *chart.Chart) error {
reqs, err := LoadRequirements(c)
if err != nil {
return err
}
// combine chart values and its dependencies' values
cvals, err := CoalesceValues(c, v)
// combine chart values and empty config to get Values
cvals, err := CoalesceValues(c, &chart.Config{})
if err != nil {
return err
}
nv := v.GetValues()
b := make(map[string]interface{}, len(nv))
// convert values to map
for kk, vvv := range nv {
b[kk] = vvv
}
b := make(map[string]interface{}, 0)
// import values from each dependency if specified in import-values
for _, r := range reqs.Dependencies {
if len(r.ImportValues) > 0 {
@ -431,10 +427,10 @@ func processImportValues(c *chart.Chart, v *chart.Config) error {
}
// ProcessRequirementsImportValues imports specified chart values from child to parent.
func ProcessRequirementsImportValues(c *chart.Chart, v *chart.Config) error {
func ProcessRequirementsImportValues(c *chart.Chart) error {
pc := getParents(c, nil)
for i := len(pc) - 1; i >= 0; i-- {
processImportValues(pc[i], v)
processImportValues(pc[i])
}
return nil

@ -282,7 +282,7 @@ func TestProcessRequirementsImportValues(t *testing.T) {
}
func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Config, e map[string]string) {
err := ProcessRequirementsImportValues(c, v)
err := ProcessRequirementsImportValues(c)
if err != nil {
t.Errorf("Error processing import values requirements %v", err)
}
@ -321,22 +321,36 @@ func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Confi
}
}
func TestCopyChartAsAlias(t *testing.T) {
func TestGetAliasDependency(t *testing.T) {
c, err := Load("testdata/frobnitz")
if err != nil {
t.Fatalf("Failed to load testdata: %s", err)
}
if aliasChart := copyChartAsAlias(c.Dependencies, "mariners", "another-mariner"); aliasChart != nil {
t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name)
req, err := LoadRequirements(c)
if err != nil {
t.Fatalf("Failed to load requirement for testdata: %s", err)
}
if len(req.Dependencies) == 0 {
t.Fatalf("There are no requirements to test")
}
aliasChart := copyChartAsAlias(c.Dependencies, "mariner", "another-mariner")
// Success case
aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0])
if aliasChart == nil {
t.Fatal("Failed to find dependent chart")
t.Fatalf("Failed to get dependency chart for alias %s", req.Dependencies[0].Name)
}
if req.Dependencies[0].Alias != "" {
if aliasChart.Metadata.Name != req.Dependencies[0].Alias {
t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Alias, aliasChart.Metadata.Name)
}
} else if aliasChart.Metadata.Name != req.Dependencies[0].Name {
t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Name, aliasChart.Metadata.Name)
}
if aliasChart.Metadata.Name != "another-mariner" {
t.Fatal(`Failed to update chart-name for alias "dependent chart`)
// Failure case
req.Dependencies[0].Name = "something-else"
if aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]); aliasChart != nil {
t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name)
}
}
@ -364,15 +378,15 @@ func TestDependentChartAliases(t *testing.T) {
t.Fatalf("Cannot load requirements for test chart, %v", err)
}
var expectedDependencyCharts int
for _, reqmt := range reqmts.Dependencies {
expectedDependencyCharts++
if len(reqmt.Alias) >= 0 {
expectedDependencyCharts += len(reqmt.Alias)
}
}
if len(c.Dependencies) != expectedDependencyCharts {
t.Fatalf("Expected number of chart dependencies %d, but got %d", expectedDependencyCharts, len(c.Dependencies))
// var expectedDependencyCharts int
// for _, reqmt := range reqmts.Dependencies {
// expectedDependencyCharts++
// if len(reqmt.Alias) >= 0 {
// expectedDependencyCharts += len(reqmt.Alias)
// }
// }
if len(c.Dependencies) != len(reqmts.Dependencies) {
t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies))
}
}

@ -5,6 +5,8 @@ dependencies:
- name: mariner
version: "4.3.2"
repository: https://example.com/charts
alias:
- mariners1
- mariners2
alias: mariners2
- name: mariner
version: "4.3.2"
repository: https://example.com/charts
alias: mariners1

@ -215,6 +215,12 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
return u, r.Client, fmt.Errorf("invalid chart URL format: %s", ref)
}
// If the URL is relative (no scheme), prepend the chart repo's base URL
if !u.IsAbs() {
u, err = url.Parse(rc.URL + "/" + u.Path)
return u, r.Client, err
}
return u, r.Client, nil
}

@ -42,6 +42,7 @@ func TestResolveChartRef(t *testing.T) {
{name: "full URL, with authentication", ref: "http://username:password@example.com/foo-1.2.3.tgz", expect: "http://username:password@example.com/foo-1.2.3.tgz"},
{name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"},
{name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"},
{name: "reference, version, malformed repo", ref: "malformed/alpine", version: "1.2.3", expect: "http://dl.example.com/alpine-1.2.3.tgz"},
{name: "full URL, HTTPS, irrelevant version", ref: "https://example.com/foo-1.2.3.tgz", version: "0.1.0", expect: "https://example.com/foo-1.2.3.tgz", fail: true},
{name: "full URL, file", ref: "file:///foo-1.2.3.tgz", fail: true},
{name: "invalid", ref: "invalid-1.2.3", fail: true},

@ -0,0 +1,16 @@
apiVersion: v1
entries:
alpine:
- name: alpine
urls:
- alpine-1.2.3.tgz
checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d
home: https://k8s.io/helm
sources:
- https://github.com/kubernetes/helm
version: 1.2.3
description: Deploy a basic Alpine Linux pod
keywords: []
maintainers: []
engine: ""
icon: ""

@ -8,3 +8,5 @@ repositories:
url: "http://username:password@example.com"
- name: kubernetes-charts
url: "http://example.com/charts"
- name: malformed
url: "http://dl.example.com"

@ -20,6 +20,7 @@ import (
"bytes"
"fmt"
"path"
"sort"
"strings"
"text/template"
@ -181,8 +182,14 @@ func (e *Engine) render(tpls map[string]renderable) (map[string]string, error) {
funcMap := e.alterFuncMap(t)
// We want to parse the templates in a predictable order. The order favors
// higher-level (in file system) templates over deeply nested templates.
keys := sortTemplates(tpls)
files := []string{}
for fname, r := range tpls {
//for fname, r := range tpls {
for _, fname := range keys {
r := tpls[fname]
t = t.New(fname).Funcs(funcMap)
if _, err := t.Parse(r.tpl); err != nil {
return map[string]string{}, fmt.Errorf("parse error in %q: %s", fname, err)
@ -215,6 +222,30 @@ func (e *Engine) render(tpls map[string]renderable) (map[string]string, error) {
return rendered, nil
}
func sortTemplates(tpls map[string]renderable) []string {
keys := make([]string, len(tpls))
i := 0
for key := range tpls {
keys[i] = key
i++
}
sort.Sort(sort.Reverse(byPathLen(keys)))
return keys
}
type byPathLen []string
func (p byPathLen) Len() int { return len(p) }
func (p byPathLen) Swap(i, j int) { p[j], p[i] = p[i], p[j] }
func (p byPathLen) Less(i, j int) bool {
a, b := p[i], p[j]
ca, cb := strings.Count(a, "/"), strings.Count(b, "/")
if ca == cb {
return strings.Compare(a, b) == -1
}
return ca < cb
}
// allTemplates returns all templates for a chart and its dependencies.
//
// As it goes, it also prepares the values in a scope-sensitive manner.

@ -27,6 +27,37 @@ import (
"github.com/golang/protobuf/ptypes/any"
)
func TestSortTemplates(t *testing.T) {
tpls := map[string]renderable{
"/mychart/templates/foo.tpl": {},
"/mychart/templates/charts/foo/charts/bar/templates/foo.tpl": {},
"/mychart/templates/bar.tpl": {},
"/mychart/templates/charts/foo/templates/bar.tpl": {},
"/mychart/templates/_foo.tpl": {},
"/mychart/templates/charts/foo/templates/foo.tpl": {},
"/mychart/templates/charts/bar/templates/foo.tpl": {},
}
got := sortTemplates(tpls)
if len(got) != len(tpls) {
t.Fatal("Sorted results are missing templates")
}
expect := []string{
"/mychart/templates/charts/foo/charts/bar/templates/foo.tpl",
"/mychart/templates/charts/foo/templates/foo.tpl",
"/mychart/templates/charts/foo/templates/bar.tpl",
"/mychart/templates/charts/bar/templates/foo.tpl",
"/mychart/templates/foo.tpl",
"/mychart/templates/bar.tpl",
"/mychart/templates/_foo.tpl",
}
for i, e := range expect {
if got[i] != e {
t.Errorf("expected %q, got %q at index %d\n\tExp: %#v\n\tGot: %#v", e, got[i], i, expect, got)
}
}
}
func TestEngine(t *testing.T) {
e := New()

@ -29,7 +29,7 @@ import (
// collectPlugins scans for getter plugins.
// This will load plugins according to the environment.
func collectPlugins(settings environment.EnvSettings) (Providers, error) {
plugins, err := plugin.FindPlugins(settings.PlugDirs)
plugins, err := plugin.FindPlugins(settings.PluginDirs())
if err != nil {
return nil, err
}

@ -32,9 +32,8 @@ func hh(debug bool) environment.EnvSettings {
}
hp := helmpath.Home(apath)
return environment.EnvSettings{
Home: hp,
PlugDirs: hp.Plugins(),
Debug: debug,
Home: hp,
Debug: debug,
}
}

@ -98,7 +98,7 @@ func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...
if err != nil {
return nil, err
}
err = chartutil.ProcessRequirementsImportValues(req.Chart, req.Values)
err = chartutil.ProcessRequirementsImportValues(req.Chart)
if err != nil {
return nil, err
}
@ -173,7 +173,7 @@ func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts
if err != nil {
return nil, err
}
err = chartutil.ProcessRequirementsImportValues(req.Chart, req.Values)
err = chartutil.ProcessRequirementsImportValues(req.Chart)
if err != nil {
return nil, err
}

@ -38,20 +38,12 @@ const (
PluginDisableEnvVar = "HELM_NO_PLUGINS"
// HostEnvVar is the HELM_HOST environment variable key.
HostEnvVar = "HELM_HOST"
// DebugEnvVar is the HELM_DEBUG environment variable key.
DebugEnvVar = "HELM_DEBUG"
)
// DefaultHelmHome gets the configured HELM_HOME, or returns the default.
func DefaultHelmHome() string {
if home := os.Getenv(HomeEnvVar); home != "" {
return home
}
return filepath.Join(os.Getenv("HOME"), ".helm")
}
// DefaultHelmHost returns the configured HELM_HOST or an empty string.
func DefaultHelmHost() string {
return os.Getenv(HostEnvVar)
}
// DefaultHelmHome is the default HELM_HOME.
var DefaultHelmHome = filepath.Join("$HOME", ".helm")
// EnvSettings describes all of the environment settings.
type EnvSettings struct {
@ -61,8 +53,14 @@ type EnvSettings struct {
TillerNamespace string
// Home is the local path to the Helm home directory.
Home helmpath.Home
// PluginDirs is the path to the plugin directories.
PlugDirs string
// Debug indicates whether or not Helm is running in Debug mode.
Debug bool
}
// PluginDirs is the path to the plugin directories.
func (s EnvSettings) PluginDirs() string {
if d := os.Getenv(PluginEnvVar); d != "" {
return d
}
return s.Home.Plugins()
}

@ -17,6 +17,7 @@ package helmpath
import (
"fmt"
"os"
"path/filepath"
)
@ -29,12 +30,12 @@ type Home string
//
// Implements fmt.Stringer.
func (h Home) String() string {
return string(h)
return os.ExpandEnv(string(h))
}
// Path returns Home with elements appended.
func (h Home) Path(elem ...string) string {
p := []string{string(h)}
p := []string{h.String()}
p = append(p, elem...)
return filepath.Join(p...)
}

@ -38,3 +38,9 @@ func TestHelmHome(t *testing.T) {
isEq(t, hh.CacheIndex("t"), "/r/repository/cache/t-index.yaml")
isEq(t, hh.Starters(), "/r/starters")
}
func TestHelmHome_expand(t *testing.T) {
if Home("$HOME").String() == "$HOME" {
t.Error("expected variable expansion")
}
}

@ -179,7 +179,7 @@ func SetupPluginEnv(settings helm_env.EnvSettings,
// Set vars that may not have been set, and save client the
// trouble of re-parsing.
helm_env.PluginEnvVar: settings.PlugDirs,
helm_env.PluginEnvVar: settings.PluginDirs(),
helm_env.HomeEnvVar: settings.Home.String(),
// Set vars that convey common information.

@ -146,7 +146,7 @@ func TestResolve(t *testing.T) {
}
func TestHashReq(t *testing.T) {
expect := "sha256:917e251ddba291096889f81eb7de713ab4e1afbbb07c576dfd7d66ba9300b12b"
expect := "sha256:45b06fcc4496c705bf3d634f8a2ff84e6a6f0bdcaf010614b8886572d1e52b99"
req := &chartutil.Requirements{
Dependencies: []*chartutil.Dependency{
{Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"},

@ -24,7 +24,6 @@ package environment
import (
"io"
"os"
"time"
"k8s.io/helm/pkg/chartutil"
@ -44,14 +43,6 @@ const TillerNamespaceEnvVar = "TILLER_NAMESPACE"
// DefaultTillerNamespace is the default namespace for tiller.
const DefaultTillerNamespace = "kube-system"
// GetTillerNamespace returns the right tiller namespace.
func GetTillerNamespace() string {
if ns := os.Getenv(TillerNamespaceEnvVar); ns != "" {
return ns
}
return DefaultTillerNamespace
}
// GoTplEngine is the name of the Go template engine, as registered in the EngineYard.
const GoTplEngine = "gotpl"

@ -51,96 +51,149 @@ type manifest struct {
head *util.SimpleHead
}
// sortManifests takes a map of filename/YAML contents and sorts them into hook types.
type result struct {
hooks []*release.Hook
generic []manifest
}
type manifestFile struct {
entries map[string]string
path string
apis chartutil.VersionSet
}
// sortManifests takes a map of filename/YAML contents, splits the file
// by manifest entries, and sorts the entries into hook types.
//
// The resulting hooks struct will be populated with all of the generated hooks.
// Any file that does not declare one of the hook types will be placed in the
// 'generic' bucket.
//
// To determine hook type, this looks for a YAML structure like this:
//
// kind: SomeKind
// apiVersion: v1
// metadata:
// annotations:
// helm.sh/hook: pre-install
//
// Where HOOK_NAME is one of the known hooks.
//
// If a file declares more than one hook, it will be copied into all of the applicable
// hook buckets. (Note: label keys are not unique within the labels section).
//
// Files that do not parse into the expected format are simply placed into a map and
// returned.
func sortManifests(files map[string]string, apis chartutil.VersionSet, sort SortOrder) ([]*release.Hook, []manifest, error) {
hs := []*release.Hook{}
generic := []manifest{}
result := &result{}
for filePath, c := range files {
for n, c := range files {
// Skip partials. We could return these as a separate map, but there doesn't
// seem to be any need for that at this time.
if strings.HasPrefix(path.Base(n), "_") {
if strings.HasPrefix(path.Base(filePath), "_") {
continue
}
// Skip empty files, and log this.
// Skip empty files and log this.
if len(strings.TrimSpace(c)) == 0 {
log.Printf("info: manifest %q is empty. Skipping.", n)
log.Printf("info: manifest %q is empty. Skipping.", filePath)
continue
}
var sh util.SimpleHead
err := yaml.Unmarshal([]byte(c), &sh)
manifestFile := &manifestFile{
entries: util.SplitManifests(c),
path: filePath,
apis: apis,
}
if err := manifestFile.sort(result); err != nil {
return result.hooks, result.generic, err
}
}
return result.hooks, sortByKind(result.generic, sort), nil
}
// sort takes a manifestFile object which may contain multiple resource definition
// entries and sorts each entry by hook types, and saves the resulting hooks and
// generic manifests (or non-hooks) to the result struct.
//
// To determine hook type, it looks for a YAML structure like this:
//
// kind: SomeKind
// apiVersion: v1
// metadata:
// annotations:
// helm.sh/hook: pre-install
//
func (file *manifestFile) sort(result *result) error {
for _, m := range file.entries {
var entry util.SimpleHead
err := yaml.Unmarshal([]byte(m), &entry)
if err != nil {
e := fmt.Errorf("YAML parse error on %s: %s", n, err)
return hs, generic, e
e := fmt.Errorf("YAML parse error on %s: %s", file.path, err)
return e
}
if sh.Version != "" && !apis.Has(sh.Version) {
return hs, generic, fmt.Errorf("apiVersion %q in %s is not available", sh.Version, n)
if entry.Version != "" && !file.apis.Has(entry.Version) {
return fmt.Errorf("apiVersion %q in %s is not available", entry.Version, file.path)
}
if sh.Metadata == nil || sh.Metadata.Annotations == nil || len(sh.Metadata.Annotations) == 0 {
generic = append(generic, manifest{name: n, content: c, head: &sh})
if !hasAnyAnnotation(entry) {
result.generic = append(result.generic, manifest{
name: file.path,
content: m,
head: &entry,
})
continue
}
hookTypes, ok := sh.Metadata.Annotations[hooks.HookAnno]
hookTypes, ok := entry.Metadata.Annotations[hooks.HookAnno]
if !ok {
generic = append(generic, manifest{name: n, content: c, head: &sh})
result.generic = append(result.generic, manifest{
name: file.path,
content: m,
head: &entry,
})
continue
}
hws, _ := sh.Metadata.Annotations[hooks.HookWeightAnno]
hw, err := strconv.Atoi(hws)
if err != nil {
hw = 0
}
hw := calculateHookWeight(entry)
h := &release.Hook{
Name: sh.Metadata.Name,
Kind: sh.Kind,
Path: n,
Manifest: c,
Name: entry.Metadata.Name,
Kind: entry.Kind,
Path: file.path,
Manifest: m,
Events: []release.Hook_Event{},
Weight: int32(hw),
Weight: hw,
}
isHook := false
isKnownHook := false
for _, hookType := range strings.Split(hookTypes, ",") {
hookType = strings.ToLower(strings.TrimSpace(hookType))
e, ok := events[hookType]
if ok {
isHook = true
isKnownHook = true
h.Events = append(h.Events, e)
}
}
if !isHook {
if !isKnownHook {
log.Printf("info: skipping unknown hook: %q", hookTypes)
continue
}
hs = append(hs, h)
result.hooks = append(result.hooks, h)
}
return nil
}
func hasAnyAnnotation(entry util.SimpleHead) bool {
if entry.Metadata == nil ||
entry.Metadata.Annotations == nil ||
len(entry.Metadata.Annotations) == 0 {
return false
}
return hs, sortByKind(generic, sort), nil
return true
}
func calculateHookWeight(entry util.SimpleHead) int32 {
hws, _ := entry.Metadata.Annotations[hooks.HookWeightAnno]
hw, err := strconv.Atoi(hws)
if err != nil {
hw = 0
}
return int32(hw)
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save