Adam Reese 7 years ago
parent 8cdebdb2d5
commit 19398a2ef1
No known key found for this signature in database
GPG Key ID: 06F35E60A7A18DD6

@ -18,13 +18,14 @@ package main // import "k8s.io/helm/cmd/helm"
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
// Import to initialize client auth plugins. // Import to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
helm_env "k8s.io/helm/pkg/helm/environment" helm_env "k8s.io/helm/pkg/helm/environment"
@ -32,7 +33,10 @@ import (
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
) )
var settings helm_env.EnvSettings var (
settings helm_env.EnvSettings
config clientcmd.ClientConfig
)
var globalUsage = `The Kubernetes package manager var globalUsage = `The Kubernetes package manager
@ -52,7 +56,6 @@ Common actions from this point include:
Environment: Environment:
$HELM_HOME set an alternative location for Helm files. By default, these are stored in ~/.helm $HELM_HOME set an alternative location for Helm files. By default, these are stored in ~/.helm
$HELM_NO_PLUGINS disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins. $HELM_NO_PLUGINS disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.
$TILLER_NAMESPACE set an alternative Tiller namespace (default "kube-system")
$KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config") $KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config")
` `
@ -67,6 +70,8 @@ func newRootCmd(args []string) *cobra.Command {
settings.AddFlags(flags) settings.AddFlags(flags)
config = kube.GetConfig(flags)
out := cmd.OutOrStdout() out := cmd.OutOrStdout()
cmd.AddCommand( cmd.AddCommand(
@ -115,6 +120,17 @@ func newRootCmd(args []string) *cobra.Command {
return cmd return cmd
} }
func init() {
log.SetFlags(log.Lshortfile)
}
func logf(format string, v ...interface{}) {
if settings.Debug {
format = fmt.Sprintf("[debug] %s\n", format)
log.Output(2, fmt.Sprintf(format, v...))
}
}
func main() { func main() {
cmd := newRootCmd(os.Args[1:]) cmd := newRootCmd(os.Args[1:])
if err := cmd.Execute(); err != nil { if err := cmd.Execute(); err != nil {
@ -143,15 +159,17 @@ func ensureHelmClient(h helm.Interface) helm.Interface {
} }
func newClient() helm.Interface { func newClient() helm.Interface {
cfg := kube.GetConfig(settings.KubeContext) kc := kube.New(config)
kc := kube.New(cfg) kc.Log = logf
clientset, err := kc.KubernetesClientSet() clientset, err := kc.KubernetesClientSet()
if err != nil { if err != nil {
// TODO return error // TODO return error
panic(err) log.Fatal(err)
} }
// TODO add other backends // TODO add other backends
cfgmaps := driver.NewConfigMaps(clientset.CoreV1().ConfigMaps(settings.TillerNamespace)) cfgmaps := driver.NewSecrets(clientset.CoreV1().Secrets(getNamespace()))
cfgmaps.Log = logf
return helm.NewClient( return helm.NewClient(
helm.KubeClient(kc), helm.KubeClient(kc),
@ -159,3 +177,10 @@ func newClient() helm.Interface {
helm.Discovery(clientset.Discovery()), helm.Discovery(clientset.Discovery()),
) )
} }
func getNamespace() string {
if ns, _, err := config.Namespace(); err == nil {
return ns
}
return "default"
}

@ -38,7 +38,6 @@ import (
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/strvals" "k8s.io/helm/pkg/strvals"
) )
@ -107,7 +106,6 @@ charts in a repository, use 'helm search'.
type installCmd struct { type installCmd struct {
name string name string
namespace string
valueFiles valueFiles valueFiles valueFiles
chartPath string chartPath string
dryRun bool dryRun bool
@ -186,7 +184,6 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
f := cmd.Flags() f := cmd.Flags()
f.VarP(&inst.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") f.VarP(&inst.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)")
f.StringVarP(&inst.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you") f.StringVarP(&inst.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you")
f.StringVar(&inst.namespace, "namespace", "n", "namespace to install the release into. Defaults to the current kube config namespace.")
f.BoolVar(&inst.dryRun, "dry-run", false, "simulate an install") f.BoolVar(&inst.dryRun, "dry-run", false, "simulate an install")
f.BoolVar(&inst.disableHooks, "no-hooks", false, "prevent hooks from running during install") f.BoolVar(&inst.disableHooks, "no-hooks", false, "prevent hooks from running during install")
f.BoolVar(&inst.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production") f.BoolVar(&inst.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production")
@ -213,10 +210,6 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
func (i *installCmd) run() error { func (i *installCmd) run() error {
debug("CHART PATH: %s\n", i.chartPath) debug("CHART PATH: %s\n", i.chartPath)
if i.namespace == "" {
i.namespace = defaultNamespace()
}
rawVals, err := vals(i.valueFiles, i.values, i.stringValues) rawVals, err := vals(i.valueFiles, i.values, i.stringValues)
if err != nil { if err != nil {
return err return err
@ -266,7 +259,7 @@ func (i *installCmd) run() error {
rel, err := i.client.InstallReleaseFromChart( rel, err := i.client.InstallReleaseFromChart(
chartRequested, chartRequested,
i.namespace, getNamespace(),
helm.ValueOverrides(rawVals), helm.ValueOverrides(rawVals),
helm.ReleaseName(i.name), helm.ReleaseName(i.name),
helm.InstallDryRun(i.dryRun), helm.InstallDryRun(i.dryRun),
@ -472,13 +465,6 @@ func generateName(nameTemplate string) (string, error) {
return b.String(), nil return b.String(), nil
} }
func defaultNamespace() string {
if ns, _, err := kube.GetConfig(settings.KubeContext).Namespace(); err == nil {
return ns
}
return "default"
}
func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements) error { func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements) error {
missing := []string{} missing := []string{}

@ -47,7 +47,6 @@ type lintCmd struct {
valueFiles valueFiles valueFiles valueFiles
values []string values []string
sValues []string sValues []string
namespace string
strict bool strict bool
paths []string paths []string
out io.Writer out io.Writer
@ -73,7 +72,6 @@ func newLintCmd(out io.Writer) *cobra.Command {
cmd.Flags().VarP(&l.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") cmd.Flags().VarP(&l.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
cmd.Flags().StringArrayVar(&l.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") cmd.Flags().StringArrayVar(&l.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringArrayVar(&l.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") cmd.Flags().StringArrayVar(&l.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringVar(&l.namespace, "namespace", "default", "namespace to install the release into (only used if --install is set)")
cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings") cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings")
return cmd return cmd
@ -98,7 +96,7 @@ func (l *lintCmd) run() error {
var total int var total int
var failures int var failures int
for _, path := range l.paths { for _, path := range l.paths {
if linter, err := lintChart(path, rvals, l.namespace, l.strict); err != nil { if linter, err := lintChart(path, rvals, getNamespace(), l.strict); err != nil {
fmt.Println("==> Skipping", path) fmt.Println("==> Skipping", path)
fmt.Println(err) fmt.Println(err)
if err == errLintNoChart { if err == errLintNoChart {

@ -69,7 +69,6 @@ type listCmd struct {
deleting bool deleting bool
deployed bool deployed bool
failed bool failed bool
namespace string
superseded bool superseded bool
pending bool pending bool
client helm.Interface client helm.Interface
@ -110,7 +109,6 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&list.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled") f.BoolVar(&list.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
f.BoolVar(&list.failed, "failed", false, "show failed releases") f.BoolVar(&list.failed, "failed", false, "show failed releases")
f.BoolVar(&list.pending, "pending", false, "show pending releases") f.BoolVar(&list.pending, "pending", false, "show pending releases")
f.StringVar(&list.namespace, "namespace", "n", "show releases within a specific namespace")
f.UintVar(&list.colWidth, "col-width", 60, "specifies the max column width of output") f.UintVar(&list.colWidth, "col-width", 60, "specifies the max column width of output")
// TODO: Do we want this as a feature of 'helm list'? // TODO: Do we want this as a feature of 'helm list'?
@ -139,7 +137,6 @@ func (l *listCmd) run() error {
helm.ReleaseListSort(int(sortBy)), helm.ReleaseListSort(int(sortBy)),
helm.ReleaseListOrder(int(sortOrder)), helm.ReleaseListOrder(int(sortOrder)),
helm.ReleaseListStatuses(stats), helm.ReleaseListStatuses(stats),
helm.ReleaseListNamespace(l.namespace),
) )
if err != nil { if err != nil {

@ -108,7 +108,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
func manuallyProcessArgs(args []string) ([]string, []string) { func manuallyProcessArgs(args []string) ([]string, []string) {
known := []string{} known := []string{}
unknown := []string{} unknown := []string{}
kvargs := []string{"--kube-context", "--home", "--tiller-namespace"} kvargs := []string{"--context", "--home", "--namespace"}
knownArg := func(a string) bool { knownArg := func(a string) bool {
for _, pre := range kvargs { for _, pre := range kvargs {
if strings.HasPrefix(a, pre+"=") { if strings.HasPrefix(a, pre+"=") {
@ -121,7 +121,7 @@ func manuallyProcessArgs(args []string) ([]string, []string) {
switch a := args[i]; a { switch a := args[i]; a {
case "--debug": case "--debug":
known = append(known, a) known = append(known, a)
case "--kube-context", "--home": case "--context", "--home", "--namespace":
known = append(known, a, args[i+1]) known = append(known, a, args[i+1])
i++ i++
default: default:

@ -33,14 +33,13 @@ func TestManuallyProcessArgs(t *testing.T) {
input := []string{ input := []string{
"--debug", "--debug",
"--foo", "bar", "--foo", "bar",
"--kube-context", "test1", "--context", "test1",
"--home=/tmp", "--home=/tmp",
"--tiller-namespace=hello",
"command", "command",
} }
expectKnown := []string{ expectKnown := []string{
"--debug", "--kube-context", "test1", "--home=/tmp", "--tiller-namespace=hello", "--debug", "--context", "test1", "--home=/tmp",
} }
expectUnknown := []string{ expectUnknown := []string{
@ -176,7 +175,6 @@ func TestSetupEnv(t *testing.T) {
{"HELM_PATH_CACHE", settings.Home.Cache()}, {"HELM_PATH_CACHE", settings.Home.Cache()},
{"HELM_PATH_LOCAL_REPOSITORY", settings.Home.LocalRepository()}, {"HELM_PATH_LOCAL_REPOSITORY", settings.Home.LocalRepository()},
{"HELM_PATH_STARTER", settings.Home.Starters()}, {"HELM_PATH_STARTER", settings.Home.Starters()},
{"TILLER_NAMESPACE", settings.TillerNamespace},
} { } {
if got := os.Getenv(tt.name); got != tt.expect { if got := os.Getenv(tt.name); got != tt.expect {
t.Errorf("Expected $%s=%q, got %q", tt.name, tt.expect, got) t.Errorf("Expected $%s=%q, got %q", tt.name, tt.expect, got)

@ -17,7 +17,6 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"io" "io"
"text/template" "text/template"
"time" "time"
@ -75,8 +74,5 @@ func tpl(t string, vals map[string]interface{}, out io.Writer) error {
} }
func debug(format string, args ...interface{}) { func debug(format string, args ...interface{}) {
if settings.Debug { logf(format, args...)
format = fmt.Sprintf("[debug] %s\n", format)
fmt.Printf(format, args...)
}
} }

@ -61,7 +61,6 @@ To render just one template in a chart, use '-x':
` `
type templateCmd struct { type templateCmd struct {
namespace string
valueFiles valueFiles valueFiles valueFiles
chartPath string chartPath string
out io.Writer out io.Writer
@ -93,7 +92,6 @@ func newTemplateCmd(out io.Writer) *cobra.Command {
f.StringVarP(&t.releaseName, "name", "", "RELEASE-NAME", "release name") f.StringVarP(&t.releaseName, "name", "", "RELEASE-NAME", "release name")
f.StringArrayVarP(&t.renderFiles, "execute", "x", []string{}, "only execute the given templates") f.StringArrayVarP(&t.renderFiles, "execute", "x", []string{}, "only execute the given templates")
f.VarP(&t.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") f.VarP(&t.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
f.StringVar(&t.namespace, "namespace", "n", "namespace to install the release into")
f.StringArrayVar(&t.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") f.StringArrayVar(&t.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&t.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") f.StringArrayVar(&t.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringVar(&t.nameTemplate, "name-template", "", "specify template used to name the release") f.StringVar(&t.nameTemplate, "name-template", "", "specify template used to name the release")
@ -145,9 +143,6 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
} }
} }
if t.namespace == "" {
t.namespace = defaultNamespace()
}
// get combined values and create config // get combined values and create config
config, err := vals(t.valueFiles, t.values, t.stringValues) config, err := vals(t.valueFiles, t.values, t.stringValues)
if err != nil { if err != nil {
@ -178,7 +173,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
options := chartutil.ReleaseOptions{ options := chartutil.ReleaseOptions{
Name: t.releaseName, Name: t.releaseName,
Time: time.Now(), Time: time.Now(),
Namespace: t.namespace, Namespace: getNamespace(),
} }
err = chartutil.ProcessRequirementsEnabled(c, config) err = chartutil.ProcessRequirementsEnabled(c, config)
@ -248,7 +243,6 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
Chart: c, Chart: c,
Config: config, Config: config,
Version: 1, Version: 1,
Namespace: t.namespace,
Info: &release.Info{LastDeployed: time.Now()}, Info: &release.Info{LastDeployed: time.Now()},
} }
printRelease(os.Stdout, rel) printRelease(os.Stdout, rel)

@ -69,13 +69,6 @@ func TestTemplateCmd(t *testing.T) {
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "protocol: TCP\n name: apache", expectValue: "protocol: TCP\n name: apache",
}, },
{
name: "check_namespace",
desc: "verify --namespace",
args: []string{chartPath, "--namespace", "test"},
expectKey: "subchart1/templates/service.yaml",
expectValue: "namespace: \"test\"",
},
{ {
name: "check_release_name", name: "check_release_name",
desc: "verify --release exists", desc: "verify --release exists",

@ -68,7 +68,6 @@ type upgradeCmd struct {
verify bool verify bool
keyring string keyring string
install bool install bool
namespace string
version string version string
timeout int64 timeout int64
resetValues bool resetValues bool
@ -125,7 +124,6 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading") f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading")
f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys") f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys")
f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install") f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
f.StringVar(&upgrade.namespace, "namespace", "n", "namespace to install the release into (only used if --install is set). Defaults to the current kube config namespace")
f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used") f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart") f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
@ -153,20 +151,7 @@ func (u *upgradeCmd) run() error {
if u.install { if u.install {
// If a release does not exist, install it. If another error occurs during // If a release does not exist, install it. If another error occurs during
// the check, ignore the error and continue with the upgrade. // the check, ignore the error and continue with the upgrade.
releaseHistory, err := u.client.ReleaseHistory(u.release, 1) _, err := u.client.ReleaseHistory(u.release, 1)
if err == nil {
if u.namespace == "" {
u.namespace = defaultNamespace()
}
previousReleaseNamespace := releaseHistory[0].Namespace
if previousReleaseNamespace != u.namespace {
fmt.Fprintf(u.out,
"WARNING: Namespace %q doesn't match with previous. Release will be deployed to %s\n",
u.namespace, previousReleaseNamespace,
)
}
}
if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) { if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) {
fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release) fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release)
@ -182,7 +167,6 @@ func (u *upgradeCmd) run() error {
keyring: u.keyring, keyring: u.keyring,
values: u.values, values: u.values,
stringValues: u.stringValues, stringValues: u.stringValues,
namespace: u.namespace,
timeout: u.timeout, timeout: u.timeout,
wait: u.wait, wait: u.wait,
} }

@ -75,8 +75,6 @@ type ListReleasesRequest struct {
// SortOrder is the ordering directive used for sorting. // SortOrder is the ordering directive used for sorting.
SortOrder ListSortOrder `json:"sort_order,omityempty"` SortOrder ListSortOrder `json:"sort_order,omityempty"`
StatusCodes []release.StatusCode `json:"status_codes,omityempty"` StatusCodes []release.StatusCode `json:"status_codes,omityempty"`
// Namespace is the filter to select releases only from a specific namespace.
Namespace string `json:"namespace,omityempty"`
} }
// ListReleasesResponse is a list of releases. // ListReleasesResponse is a list of releases.

@ -37,22 +37,16 @@ var DefaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm")
// EnvSettings describes all of the environment settings. // EnvSettings describes all of the environment settings.
type EnvSettings struct { type EnvSettings struct {
// TillerNamespace is the namespace in which Tiller runs.
TillerNamespace string
// Home is the local path to the Helm home directory. // Home is the local path to the Helm home directory.
Home helmpath.Home Home helmpath.Home
// Debug indicates whether or not Helm is running in Debug mode. // Debug indicates whether or not Helm is running in Debug mode.
Debug bool Debug bool
// KubeContext is the name of the kubeconfig context.
KubeContext string
} }
// AddFlags binds flags to the given flagset. // AddFlags binds flags to the given flagset.
func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) { func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
fs.StringVar((*string)(&s.Home), "home", DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME") fs.StringVar((*string)(&s.Home), "home", DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
fs.StringVar(&s.KubeContext, "kube-context", "", "name of the kubeconfig context to use")
fs.BoolVar(&s.Debug, "debug", false, "enable verbose output") fs.BoolVar(&s.Debug, "debug", false, "enable verbose output")
fs.StringVar(&s.TillerNamespace, "tiller-namespace", "kube-system", "namespace of Tiller")
} }
// Init sets values from the environment. // Init sets values from the environment.
@ -74,7 +68,6 @@ func (s EnvSettings) PluginDirs() string {
var envMap = map[string]string{ var envMap = map[string]string{
"debug": "HELM_DEBUG", "debug": "HELM_DEBUG",
"home": "HELM_HOME", "home": "HELM_HOME",
"tiller-namespace": "TILLER_NAMESPACE",
} }
func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) { func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) {
@ -85,11 +78,3 @@ func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) {
fs.Set(name, v) fs.Set(name, v)
} }
} }
// Deprecated
const (
HomeEnvVar = "HELM_HOME"
PluginEnvVar = "HELM_PLUGIN"
PluginDisableEnvVar = "HELM_NO_PLUGINS"
DebugEnvVar = "HELM_DEBUG"
)

@ -35,7 +35,7 @@ func TestEnvSettings(t *testing.T) {
envars map[string]string envars map[string]string
// expected values // expected values
home, ns, kcontext, plugins string home, ns, plugins string
debug bool debug bool
}{ }{
{ {
@ -47,7 +47,7 @@ func TestEnvSettings(t *testing.T) {
}, },
{ {
name: "with flags set", name: "with flags set",
args: []string{"--home", "/foo", "--debug", "--tiller-namespace=myns"}, args: []string{"--home", "/foo", "--debug"},
home: "/foo", home: "/foo",
plugins: helmpath.Home("/foo").Plugins(), plugins: helmpath.Home("/foo").Plugins(),
ns: "myns", ns: "myns",
@ -56,7 +56,7 @@ func TestEnvSettings(t *testing.T) {
{ {
name: "with envvars set", name: "with envvars set",
args: []string{}, args: []string{},
envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns"}, envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1"},
home: "/bar", home: "/bar",
plugins: helmpath.Home("/bar").Plugins(), plugins: helmpath.Home("/bar").Plugins(),
ns: "yourns", ns: "yourns",
@ -64,8 +64,8 @@ func TestEnvSettings(t *testing.T) {
}, },
{ {
name: "with flags and envvars set", name: "with flags and envvars set",
args: []string{"--home", "/foo", "--debug", "--tiller-namespace=myns"}, args: []string{"--home", "/foo", "--debug"},
envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"}, envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "HELM_PLUGIN": "glade"},
home: "/foo", home: "/foo",
plugins: "glade", plugins: "glade",
ns: "myns", ns: "myns",
@ -99,12 +99,6 @@ func TestEnvSettings(t *testing.T) {
if settings.Debug != tt.debug { if settings.Debug != tt.debug {
t.Errorf("expected debug %t, got %t", tt.debug, settings.Debug) t.Errorf("expected debug %t, got %t", tt.debug, settings.Debug)
} }
if settings.TillerNamespace != tt.ns {
t.Errorf("expected tiller-namespace %q, got %q", tt.ns, settings.TillerNamespace)
}
if settings.KubeContext != tt.kcontext {
t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext)
}
cleanup() cleanup()
}) })

@ -48,7 +48,6 @@ func TestListReleases_VerifyOptions(t *testing.T) {
rls.Status_DEPLOYED, rls.Status_DEPLOYED,
rls.Status_SUPERSEDED, rls.Status_SUPERSEDED,
} }
var namespace = "namespace"
// Expected ListReleasesRequest message // Expected ListReleasesRequest message
exp := &hapi.ListReleasesRequest{ exp := &hapi.ListReleasesRequest{
@ -58,7 +57,6 @@ func TestListReleases_VerifyOptions(t *testing.T) {
SortBy: hapi.ListSortBy(sortBy), SortBy: hapi.ListSortBy(sortBy),
SortOrder: hapi.ListSortOrder(sortOrd), SortOrder: hapi.ListSortOrder(sortOrd),
StatusCodes: codes, StatusCodes: codes,
Namespace: namespace,
} }
// Options used in ListReleases // Options used in ListReleases
@ -69,7 +67,6 @@ func TestListReleases_VerifyOptions(t *testing.T) {
ReleaseListOffset(offset), ReleaseListOffset(offset),
ReleaseListFilter(filter), ReleaseListFilter(filter),
ReleaseListStatuses(codes), ReleaseListStatuses(codes),
ReleaseListNamespace(namespace),
} }
// BeforeCall option to intercept Helm client ListReleasesRequest // BeforeCall option to intercept Helm client ListReleasesRequest
@ -99,7 +96,6 @@ func TestInstallRelease_VerifyOptions(t *testing.T) {
// Options testdata // Options testdata
var disableHooks = true var disableHooks = true
var releaseName = "test" var releaseName = "test"
var namespace = "default"
var reuseName = true var reuseName = true
var dryRun = true var dryRun = true
var chartName = "alpine" var chartName = "alpine"
@ -113,7 +109,6 @@ func TestInstallRelease_VerifyOptions(t *testing.T) {
DryRun: dryRun, DryRun: dryRun,
Name: releaseName, Name: releaseName,
DisableHooks: disableHooks, DisableHooks: disableHooks,
Namespace: namespace,
ReuseName: reuseName, ReuseName: reuseName,
} }
@ -139,7 +134,7 @@ func TestInstallRelease_VerifyOptions(t *testing.T) {
}) })
client := NewClient(b4c) client := NewClient(b4c)
if _, err := client.InstallRelease(chartPath, namespace, ops...); err != errSkip { if _, err := client.InstallRelease(chartPath, "", ops...); err != errSkip {
t.Fatalf("did not expect error but got (%v)\n``", err) t.Fatalf("did not expect error but got (%v)\n``", err)
} }

@ -138,13 +138,6 @@ func ReleaseListStatuses(statuses []release.StatusCode) ReleaseListOption {
} }
} }
// ReleaseListNamespace specifies the namespace to list releases from
func ReleaseListNamespace(namespace string) ReleaseListOption {
return func(opts *options) {
opts.listReq.Namespace = namespace
}
}
// InstallOption allows specifying various settings // InstallOption allows specifying various settings
// configurable by the helm client user for overriding // configurable by the helm client user for overriding
// the defaults used when running the `helm install` command. // the defaults used when running the `helm install` command.

@ -35,7 +35,6 @@ import (
extv1beta1 "k8s.io/api/extensions/v1beta1" extv1beta1 "k8s.io/api/extensions/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -65,9 +64,6 @@ var ErrNoObjectsVisited = goerrors.New("no objects visited")
// Client represents a client capable of communicating with the Kubernetes API. // Client represents a client capable of communicating with the Kubernetes API.
type Client struct { type Client struct {
cmdutil.Factory cmdutil.Factory
// SchemaCacheDir is the path for loading cached schema.
SchemaCacheDir string
Log func(string, ...interface{}) Log func(string, ...interface{})
} }
@ -75,7 +71,6 @@ type Client struct {
func New(config clientcmd.ClientConfig) *Client { func New(config clientcmd.ClientConfig) *Client {
return &Client{ return &Client{
Factory: cmdutil.NewFactory(config), Factory: cmdutil.NewFactory(config),
SchemaCacheDir: clientcmd.RecommendedSchemaFile,
Log: nopLogger, Log: nopLogger,
} }
} }
@ -89,18 +84,11 @@ type ResourceActorFunc func(*resource.Info) error
// //
// Namespace will set the namespace. // Namespace will set the namespace.
func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shouldWait bool) error { func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shouldWait bool) error {
client, err := c.ClientSet() c.Log("building resources from manifest")
infos, err := c.BuildUnstructured(namespace, reader)
if err != nil { if err != nil {
return err return err
} }
if err := ensureNamespace(client, namespace); err != nil {
return err
}
c.Log("building resources from manifest")
infos, buildErr := c.BuildUnstructured(namespace, reader)
if buildErr != nil {
return buildErr
}
c.Log("creating %d resource(s)", len(infos)) c.Log("creating %d resource(s)", len(infos))
if err := perform(infos, createResource); err != nil { if err := perform(infos, createResource); err != nil {
return err return err
@ -111,13 +99,21 @@ func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shoul
return nil return nil
} }
func (c *Client) namespace() string {
if ns, _, err := c.DefaultNamespace(); err == nil {
return ns
}
return v1.NamespaceDefault
}
func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Result { func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Result {
return c.NewBuilder(). return c.NewBuilder().
Internal(). Internal().
ContinueOnError(). ContinueOnError().
Schema(c.validator()). Schema(c.validator()).
NamespaceParam(namespace). NamespaceParam(c.namespace()).
DefaultNamespace(). DefaultNamespace().
RequireNamespace().
Stream(reader, ""). Stream(reader, "").
Flatten(). Flatten().
Do() Do()
@ -138,8 +134,9 @@ func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result,
result, err := c.NewBuilder(). result, err := c.NewBuilder().
Unstructured(). Unstructured().
ContinueOnError(). ContinueOnError().
NamespaceParam(namespace). NamespaceParam(c.namespace()).
DefaultNamespace(). DefaultNamespace().
RequireNamespace().
Stream(reader, ""). Stream(reader, "").
Flatten(). Flatten().
Do().Infos() Do().Infos()
@ -393,12 +390,12 @@ func deleteResource(c *Client, info *resource.Info) error {
return reaper.Stop(info.Namespace, info.Name, 0, nil) return reaper.Stop(info.Namespace, info.Name, 0, nil)
} }
func createPatch(mapping *meta.RESTMapping, target, current runtime.Object) ([]byte, types.PatchType, error) { func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) {
oldData, err := json.Marshal(current) oldData, err := json.Marshal(current)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, fmt.Errorf("serializing current configuration: %s", err) return nil, types.StrategicMergePatchType, fmt.Errorf("serializing current configuration: %s", err)
} }
newData, err := json.Marshal(target) newData, err := json.Marshal(target.Object)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, fmt.Errorf("serializing target configuration: %s", err) return nil, types.StrategicMergePatchType, fmt.Errorf("serializing target configuration: %s", err)
} }
@ -412,7 +409,7 @@ func createPatch(mapping *meta.RESTMapping, target, current runtime.Object) ([]b
} }
// Get a versioned object // Get a versioned object
versionedObject, err := mapping.ConvertToVersion(target, mapping.GroupVersionKind.GroupVersion()) versionedObject, err := target.Versioned()
// Unstructured objects, such as CRDs, may not have an not registered error // Unstructured objects, such as CRDs, may not have an not registered error
// returned from ConvertToVersion. Anything that's unstructured should // returned from ConvertToVersion. Anything that's unstructured should
@ -434,7 +431,7 @@ func createPatch(mapping *meta.RESTMapping, target, current runtime.Object) ([]b
} }
func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool, recreate bool) error { func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool, recreate bool) error {
patch, patchType, err := createPatch(target.Mapping, target.Object, currentObj) patch, patchType, err := createPatch(target, currentObj)
if err != nil { if err != nil {
return fmt.Errorf("failed to create patch: %s", err) return fmt.Errorf("failed to create patch: %s", err)
} }

@ -123,14 +123,10 @@ type testClient struct {
func newTestClient() *testClient { func newTestClient() *testClient {
tf := cmdtesting.NewTestFactory() tf := cmdtesting.NewTestFactory()
c := &Client{ tf.Namespace = core.NamespaceDefault
Factory: tf,
Log: nopLogger, c := &Client{Factory: tf, Log: nopLogger}
} return &testClient{Client: c, TestFactory: tf}
return &testClient{
Client: c,
TestFactory: tf,
}
} }
func TestUpdate(t *testing.T) { func TestUpdate(t *testing.T) {
@ -181,6 +177,7 @@ func TestUpdate(t *testing.T) {
} }
c := newTestClient() c := newTestClient()
tf.Namespace = core.NamespaceDefault
reaper := &fakeReaper{} reaper := &fakeReaper{}
rf := &fakeReaperFactory{Factory: tf, reaper: reaper} rf := &fakeReaperFactory{Factory: tf, reaper: reaper}
c.Client.Factory = rf c.Client.Factory = rf
@ -309,7 +306,6 @@ func TestGet(t *testing.T) {
func TestPerform(t *testing.T) { func TestPerform(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
namespace string
reader io.Reader reader io.Reader
count int count int
err bool err bool
@ -317,12 +313,10 @@ func TestPerform(t *testing.T) {
}{ }{
{ {
name: "Valid input", name: "Valid input",
namespace: "test",
reader: strings.NewReader(guestbookManifest), reader: strings.NewReader(guestbookManifest),
count: 6, count: 6,
}, { }, {
name: "Empty manifests", name: "Empty manifests",
namespace: "test",
reader: strings.NewReader(""), reader: strings.NewReader(""),
err: true, err: true,
errMessage: "no objects visited", errMessage: "no objects visited",
@ -335,16 +329,12 @@ func TestPerform(t *testing.T) {
fn := func(info *resource.Info) error { fn := func(info *resource.Info) error {
results = append(results, info) results = append(results, info)
if info.Namespace != tt.namespace {
t.Errorf("expected namespace to be '%s', got %s", tt.namespace, info.Namespace)
}
return nil return nil
} }
c := newTestClient() c := newTestClient()
defer c.Cleanup() defer c.Cleanup()
infos, err := c.Build(tt.namespace, tt.reader) infos, err := c.Build("default", tt.reader)
if err != nil && err.Error() != tt.errMessage { if err != nil && err.Error() != tt.errMessage {
t.Errorf("Error while building manifests: %v", err) t.Errorf("Error while building manifests: %v", err)
} }

@ -16,17 +16,21 @@ limitations under the License.
package kube // import "k8s.io/helm/pkg/kube" package kube // import "k8s.io/helm/pkg/kube"
import "k8s.io/client-go/tools/clientcmd" import (
"github.com/spf13/pflag"
"k8s.io/client-go/tools/clientcmd"
)
// GetConfig returns a Kubernetes client config for a given context. // GetConfig returns a Kubernetes client config for a given context.
func GetConfig(context string) clientcmd.ClientConfig { func GetConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
rules := clientcmd.NewDefaultClientConfigLoadingRules() rules := clientcmd.NewDefaultClientConfigLoadingRules()
rules.DefaultClientConfig = &clientcmd.DefaultClientConfig rules.DefaultClientConfig = &clientcmd.DefaultClientConfig
flags.StringVar(&rules.ExplicitPath, "kubeconfig", "", "path to the kubeconfig file to use for CLI requests")
overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults} overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}
flags.StringVarP(&overrides.Context.Namespace, "namespace", "n", "", "if present, the namespace scope for this CLI request")
flags.StringVar(&overrides.CurrentContext, "context", "", "the name of the kubeconfig context to use")
if context != "" {
overrides.CurrentContext = context
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides) return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides)
} }

@ -1,46 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kube // import "k8s.io/helm/pkg/kube"
import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
)
func createNamespace(client internalclientset.Interface, namespace string) error {
ns := &core.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
},
}
_, err := client.Core().Namespaces().Create(ns)
return err
}
func getNamespace(client internalclientset.Interface, namespace string) (*core.Namespace, error) {
return client.Core().Namespaces().Get(namespace, metav1.GetOptions{})
}
func ensureNamespace(client internalclientset.Interface, namespace string) error {
_, err := getNamespace(client, namespace)
if err != nil && errors.IsNotFound(err) {
return createNamespace(client, namespace)
}
return err
}

@ -1,37 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kube // import "k8s.io/helm/pkg/kube"
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
)
func TestEnsureNamespace(t *testing.T) {
client := fake.NewSimpleClientset()
if err := ensureNamespace(client, "foo"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := ensureNamespace(client, "foo"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if _, err := client.Core().Namespaces().Get("foo", metav1.GetOptions{}); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}

@ -182,8 +182,6 @@ func SetupPluginEnv(settings helm_env.EnvSettings,
"HELM_PATH_CACHE": settings.Home.Cache(), "HELM_PATH_CACHE": settings.Home.Cache(),
"HELM_PATH_LOCAL_REPOSITORY": settings.Home.LocalRepository(), "HELM_PATH_LOCAL_REPOSITORY": settings.Home.LocalRepository(),
"HELM_PATH_STARTER": settings.Home.Starters(), "HELM_PATH_STARTER": settings.Home.Starters(),
"TILLER_NAMESPACE": settings.TillerNamespace,
} { } {
os.Setenv(key, val) os.Setenv(key, val)
} }

@ -253,6 +253,7 @@ func newSecretsObject(key string, rls *rspb.Release, lbs labels) (*v1.Secret, er
Name: key, Name: key,
Labels: lbs.toMap(), Labels: lbs.toMap(),
}, },
Type: "helm.sh/release",
Data: map[string][]byte{"release": []byte(s)}, Data: map[string][]byte{"release": []byte(s)},
}, nil }, nil
} }

@ -37,9 +37,6 @@ import (
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
) )
// DefaultTillerNamespace is the default namespace for Tiller.
const DefaultTillerNamespace = "kube-system"
// GoTplEngine is the name of the Go template engine, as registered in the EngineYard. // GoTplEngine is the name of the Go template engine, as registered in the EngineYard.
const GoTplEngine = "gotpl" const GoTplEngine = "gotpl"

@ -42,10 +42,6 @@ func (s *ReleaseServer) ListReleases(req *hapi.ListReleasesRequest) ([]*release.
return nil, err return nil, err
} }
if req.Namespace != "" {
rels = filterByNamespace(req.Namespace, rels)
}
if len(req.Filter) != 0 { if len(req.Filter) != 0 {
rels, err = filterReleases(req.Filter, rels) rels, err = filterReleases(req.Filter, rels)
if err != nil { if err != nil {
@ -72,16 +68,6 @@ func (s *ReleaseServer) ListReleases(req *hapi.ListReleasesRequest) ([]*release.
return rels, nil return rels, nil
} }
func filterByNamespace(namespace string, rels []*release.Release) []*release.Release {
matches := []*release.Release{}
for _, r := range rels {
if namespace == r.Namespace {
matches = append(matches, r)
}
}
return matches
}
func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) { func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) {
preg, err := regexp.Compile(filter) preg, err := regexp.Compile(filter)
if err != nil { if err != nil {

@ -189,45 +189,3 @@ func TestListReleasesFilter(t *testing.T) {
t.Errorf("Unexpected sort order: %v.", rels) t.Errorf("Unexpected sort order: %v.", rels)
} }
} }
func TestReleasesNamespace(t *testing.T) {
rs := rsFixture()
names := []string{
"axon",
"dendrite",
"neuron",
"ribosome",
}
namespaces := []string{
"default",
"test123",
"test123",
"cerebellum",
}
num := 4
for i := 0; i < num; i++ {
rel := releaseStub()
rel.Name = names[i]
rel.Namespace = namespaces[i]
if err := rs.env.Releases.Create(rel); err != nil {
t.Fatalf("Could not store mock release: %s", err)
}
}
req := &hapi.ListReleasesRequest{
Offset: "",
Limit: 64,
Namespace: "test123",
}
rels, err := rs.ListReleases(req)
if err != nil {
t.Fatalf("Failed listing: %s", err)
}
if len(rels) != 2 {
t.Errorf("Expected 2 releases, got %d", len(rels))
}
}

Loading…
Cancel
Save