From 19398a2ef13d191bf6c1cd9a367278389540b0fd Mon Sep 17 00:00:00 2001 From: Adam Reese Date: Sun, 22 Apr 2018 01:23:19 -0700 Subject: [PATCH] feat(*): store release History in same namespace as release https://github.com/kubernetes-helm/community/blob/master/helm-v3/003-state.md#namespacing-changes --- cmd/helm/helm.go | 39 ++++++++++++++++---- cmd/helm/install.go | 16 +-------- cmd/helm/lint.go | 4 +-- cmd/helm/list.go | 3 -- cmd/helm/load_plugins.go | 4 +-- cmd/helm/plugin_test.go | 6 ++-- cmd/helm/printer.go | 6 +--- cmd/helm/template.go | 18 ++++------ cmd/helm/template_test.go | 7 ---- cmd/helm/upgrade.go | 18 +--------- pkg/hapi/tiller.go | 2 -- pkg/helm/environment/environment.go | 19 ++-------- pkg/helm/environment/environment_test.go | 18 ++++------ pkg/helm/helm_test.go | 7 +--- pkg/helm/option.go | 7 ---- pkg/kube/client.go | 41 ++++++++++----------- pkg/kube/client_test.go | 28 +++++---------- pkg/kube/config.go | 14 +++++--- pkg/kube/namespace.go | 46 ------------------------ pkg/kube/namespace_test.go | 37 ------------------- pkg/plugin/plugin.go | 2 -- pkg/storage/driver/secrets.go | 1 + pkg/tiller/environment/environment.go | 3 -- pkg/tiller/release_list.go | 14 -------- pkg/tiller/release_list_test.go | 42 ---------------------- 25 files changed, 93 insertions(+), 309 deletions(-) delete mode 100644 pkg/kube/namespace.go delete mode 100644 pkg/kube/namespace_test.go diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index ce3385cb3..5f6adcf5a 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -18,13 +18,14 @@ package main // import "k8s.io/helm/cmd/helm" import ( "fmt" + "log" "os" "strings" "github.com/spf13/cobra" - // Import to initialize client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/client-go/tools/clientcmd" "k8s.io/helm/pkg/helm" helm_env "k8s.io/helm/pkg/helm/environment" @@ -32,7 +33,10 @@ import ( "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 @@ -52,7 +56,6 @@ Common actions from this point include: Environment: $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. - $TILLER_NAMESPACE set an alternative Tiller namespace (default "kube-system") $KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config") ` @@ -67,6 +70,8 @@ func newRootCmd(args []string) *cobra.Command { settings.AddFlags(flags) + config = kube.GetConfig(flags) + out := cmd.OutOrStdout() cmd.AddCommand( @@ -115,6 +120,17 @@ func newRootCmd(args []string) *cobra.Command { 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() { cmd := newRootCmd(os.Args[1:]) if err := cmd.Execute(); err != nil { @@ -143,15 +159,17 @@ func ensureHelmClient(h helm.Interface) helm.Interface { } func newClient() helm.Interface { - cfg := kube.GetConfig(settings.KubeContext) - kc := kube.New(cfg) + kc := kube.New(config) + kc.Log = logf + clientset, err := kc.KubernetesClientSet() if err != nil { // TODO return error - panic(err) + log.Fatal(err) } // 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( helm.KubeClient(kc), @@ -159,3 +177,10 @@ func newClient() helm.Interface { helm.Discovery(clientset.Discovery()), ) } + +func getNamespace() string { + if ns, _, err := config.Namespace(); err == nil { + return ns + } + return "default" +} diff --git a/cmd/helm/install.go b/cmd/helm/install.go index ed2f11da8..d203dfd5f 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -38,7 +38,6 @@ import ( "k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/helm" - "k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/strvals" ) @@ -107,7 +106,6 @@ charts in a repository, use 'helm search'. type installCmd struct { name string - namespace string valueFiles valueFiles chartPath string dryRun bool @@ -186,7 +184,6 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { f := cmd.Flags() 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.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.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") @@ -213,10 +210,6 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { func (i *installCmd) run() error { debug("CHART PATH: %s\n", i.chartPath) - if i.namespace == "" { - i.namespace = defaultNamespace() - } - rawVals, err := vals(i.valueFiles, i.values, i.stringValues) if err != nil { return err @@ -266,7 +259,7 @@ func (i *installCmd) run() error { rel, err := i.client.InstallReleaseFromChart( chartRequested, - i.namespace, + getNamespace(), helm.ValueOverrides(rawVals), helm.ReleaseName(i.name), helm.InstallDryRun(i.dryRun), @@ -472,13 +465,6 @@ func generateName(nameTemplate string) (string, error) { 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 { missing := []string{} diff --git a/cmd/helm/lint.go b/cmd/helm/lint.go index 63f11c062..54c7f0db3 100644 --- a/cmd/helm/lint.go +++ b/cmd/helm/lint.go @@ -47,7 +47,6 @@ type lintCmd struct { valueFiles valueFiles values []string sValues []string - namespace string strict bool paths []string 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().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().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") return cmd @@ -98,7 +96,7 @@ func (l *lintCmd) run() error { var total int var failures int 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(err) if err == errLintNoChart { diff --git a/cmd/helm/list.go b/cmd/helm/list.go index 08650fecf..793512c72 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -69,7 +69,6 @@ type listCmd struct { deleting bool deployed bool failed bool - namespace string superseded bool pending bool 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.failed, "failed", false, "show failed 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") // 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.ReleaseListOrder(int(sortOrder)), helm.ReleaseListStatuses(stats), - helm.ReleaseListNamespace(l.namespace), ) if err != nil { diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go index 48bb12c61..73b76ec61 100644 --- a/cmd/helm/load_plugins.go +++ b/cmd/helm/load_plugins.go @@ -108,7 +108,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) { func manuallyProcessArgs(args []string) ([]string, []string) { known := []string{} unknown := []string{} - kvargs := []string{"--kube-context", "--home", "--tiller-namespace"} + kvargs := []string{"--context", "--home", "--namespace"} knownArg := func(a string) bool { for _, pre := range kvargs { if strings.HasPrefix(a, pre+"=") { @@ -121,7 +121,7 @@ func manuallyProcessArgs(args []string) ([]string, []string) { switch a := args[i]; a { case "--debug": known = append(known, a) - case "--kube-context", "--home": + case "--context", "--home", "--namespace": known = append(known, a, args[i+1]) i++ default: diff --git a/cmd/helm/plugin_test.go b/cmd/helm/plugin_test.go index d8a8a68c2..ef130fb4d 100644 --- a/cmd/helm/plugin_test.go +++ b/cmd/helm/plugin_test.go @@ -33,14 +33,13 @@ func TestManuallyProcessArgs(t *testing.T) { input := []string{ "--debug", "--foo", "bar", - "--kube-context", "test1", + "--context", "test1", "--home=/tmp", - "--tiller-namespace=hello", "command", } expectKnown := []string{ - "--debug", "--kube-context", "test1", "--home=/tmp", "--tiller-namespace=hello", + "--debug", "--context", "test1", "--home=/tmp", } expectUnknown := []string{ @@ -176,7 +175,6 @@ func TestSetupEnv(t *testing.T) { {"HELM_PATH_CACHE", settings.Home.Cache()}, {"HELM_PATH_LOCAL_REPOSITORY", settings.Home.LocalRepository()}, {"HELM_PATH_STARTER", settings.Home.Starters()}, - {"TILLER_NAMESPACE", settings.TillerNamespace}, } { if got := os.Getenv(tt.name); got != tt.expect { t.Errorf("Expected $%s=%q, got %q", tt.name, tt.expect, got) diff --git a/cmd/helm/printer.go b/cmd/helm/printer.go index 01210a89c..318832d09 100644 --- a/cmd/helm/printer.go +++ b/cmd/helm/printer.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "fmt" "io" "text/template" "time" @@ -75,8 +74,5 @@ func tpl(t string, vals map[string]interface{}, out io.Writer) error { } func debug(format string, args ...interface{}) { - if settings.Debug { - format = fmt.Sprintf("[debug] %s\n", format) - fmt.Printf(format, args...) - } + logf(format, args...) } diff --git a/cmd/helm/template.go b/cmd/helm/template.go index d35701ba3..d89061235 100644 --- a/cmd/helm/template.go +++ b/cmd/helm/template.go @@ -61,7 +61,6 @@ To render just one template in a chart, use '-x': ` type templateCmd struct { - namespace string valueFiles valueFiles chartPath string out io.Writer @@ -93,7 +92,6 @@ func newTemplateCmd(out io.Writer) *cobra.Command { f.StringVarP(&t.releaseName, "name", "", "RELEASE-NAME", "release name") 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.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.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") @@ -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 config, err := vals(t.valueFiles, t.values, t.stringValues) if err != nil { @@ -178,7 +173,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { options := chartutil.ReleaseOptions{ Name: t.releaseName, Time: time.Now(), - Namespace: t.namespace, + Namespace: getNamespace(), } err = chartutil.ProcessRequirementsEnabled(c, config) @@ -244,12 +239,11 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { } if settings.Debug { rel := &release.Release{ - Name: t.releaseName, - Chart: c, - Config: config, - Version: 1, - Namespace: t.namespace, - Info: &release.Info{LastDeployed: time.Now()}, + Name: t.releaseName, + Chart: c, + Config: config, + Version: 1, + Info: &release.Info{LastDeployed: time.Now()}, } printRelease(os.Stdout, rel) } diff --git a/cmd/helm/template_test.go b/cmd/helm/template_test.go index eefa46774..82eadcad0 100644 --- a/cmd/helm/template_test.go +++ b/cmd/helm/template_test.go @@ -69,13 +69,6 @@ func TestTemplateCmd(t *testing.T) { expectKey: "subchart1/templates/service.yaml", 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", desc: "verify --release exists", diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 8415ab21e..abb7fd7c4 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -68,7 +68,6 @@ type upgradeCmd struct { verify bool keyring string install bool - namespace string version string timeout int64 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.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.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.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") @@ -153,20 +151,7 @@ func (u *upgradeCmd) run() error { if u.install { // If a release does not exist, install it. If another error occurs during // the check, ignore the error and continue with the upgrade. - releaseHistory, 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, - ) - } - } + _, err := u.client.ReleaseHistory(u.release, 1) 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) @@ -182,7 +167,6 @@ func (u *upgradeCmd) run() error { keyring: u.keyring, values: u.values, stringValues: u.stringValues, - namespace: u.namespace, timeout: u.timeout, wait: u.wait, } diff --git a/pkg/hapi/tiller.go b/pkg/hapi/tiller.go index 56ca66ed7..2a7a2da5b 100644 --- a/pkg/hapi/tiller.go +++ b/pkg/hapi/tiller.go @@ -75,8 +75,6 @@ type ListReleasesRequest struct { // SortOrder is the ordering directive used for sorting. SortOrder ListSortOrder `json:"sort_order,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. diff --git a/pkg/helm/environment/environment.go b/pkg/helm/environment/environment.go index aa15f3a12..1cc6447e6 100644 --- a/pkg/helm/environment/environment.go +++ b/pkg/helm/environment/environment.go @@ -37,22 +37,16 @@ var DefaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm") // EnvSettings describes all of the environment settings. type EnvSettings struct { - // TillerNamespace is the namespace in which Tiller runs. - TillerNamespace string // Home is the local path to the Helm home directory. Home helmpath.Home // Debug indicates whether or not Helm is running in Debug mode. Debug bool - // KubeContext is the name of the kubeconfig context. - KubeContext string } // AddFlags binds flags to the given 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(&s.KubeContext, "kube-context", "", "name of the kubeconfig context to use") 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. @@ -72,9 +66,8 @@ func (s EnvSettings) PluginDirs() string { // envMap maps flag names to envvars var envMap = map[string]string{ - "debug": "HELM_DEBUG", - "home": "HELM_HOME", - "tiller-namespace": "TILLER_NAMESPACE", + "debug": "HELM_DEBUG", + "home": "HELM_HOME", } func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) { @@ -85,11 +78,3 @@ func setFlagFromEnv(name, envar string, fs *pflag.FlagSet) { fs.Set(name, v) } } - -// Deprecated -const ( - HomeEnvVar = "HELM_HOME" - PluginEnvVar = "HELM_PLUGIN" - PluginDisableEnvVar = "HELM_NO_PLUGINS" - DebugEnvVar = "HELM_DEBUG" -) diff --git a/pkg/helm/environment/environment_test.go b/pkg/helm/environment/environment_test.go index 4790ed715..52f51fa66 100644 --- a/pkg/helm/environment/environment_test.go +++ b/pkg/helm/environment/environment_test.go @@ -35,8 +35,8 @@ func TestEnvSettings(t *testing.T) { envars map[string]string // expected values - home, ns, kcontext, plugins string - debug bool + home, ns, plugins string + debug bool }{ { name: "defaults", @@ -47,7 +47,7 @@ func TestEnvSettings(t *testing.T) { }, { name: "with flags set", - args: []string{"--home", "/foo", "--debug", "--tiller-namespace=myns"}, + args: []string{"--home", "/foo", "--debug"}, home: "/foo", plugins: helmpath.Home("/foo").Plugins(), ns: "myns", @@ -56,7 +56,7 @@ func TestEnvSettings(t *testing.T) { { name: "with envvars set", 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", plugins: helmpath.Home("/bar").Plugins(), ns: "yourns", @@ -64,8 +64,8 @@ func TestEnvSettings(t *testing.T) { }, { name: "with flags and envvars set", - args: []string{"--home", "/foo", "--debug", "--tiller-namespace=myns"}, - envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "TILLER_NAMESPACE": "yourns", "HELM_PLUGIN": "glade"}, + args: []string{"--home", "/foo", "--debug"}, + envars: map[string]string{"HELM_HOME": "/bar", "HELM_DEBUG": "1", "HELM_PLUGIN": "glade"}, home: "/foo", plugins: "glade", ns: "myns", @@ -99,12 +99,6 @@ func TestEnvSettings(t *testing.T) { if settings.Debug != tt.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() }) diff --git a/pkg/helm/helm_test.go b/pkg/helm/helm_test.go index d94d0744e..57d47a684 100644 --- a/pkg/helm/helm_test.go +++ b/pkg/helm/helm_test.go @@ -48,7 +48,6 @@ func TestListReleases_VerifyOptions(t *testing.T) { rls.Status_DEPLOYED, rls.Status_SUPERSEDED, } - var namespace = "namespace" // Expected ListReleasesRequest message exp := &hapi.ListReleasesRequest{ @@ -58,7 +57,6 @@ func TestListReleases_VerifyOptions(t *testing.T) { SortBy: hapi.ListSortBy(sortBy), SortOrder: hapi.ListSortOrder(sortOrd), StatusCodes: codes, - Namespace: namespace, } // Options used in ListReleases @@ -69,7 +67,6 @@ func TestListReleases_VerifyOptions(t *testing.T) { ReleaseListOffset(offset), ReleaseListFilter(filter), ReleaseListStatuses(codes), - ReleaseListNamespace(namespace), } // BeforeCall option to intercept Helm client ListReleasesRequest @@ -99,7 +96,6 @@ func TestInstallRelease_VerifyOptions(t *testing.T) { // Options testdata var disableHooks = true var releaseName = "test" - var namespace = "default" var reuseName = true var dryRun = true var chartName = "alpine" @@ -113,7 +109,6 @@ func TestInstallRelease_VerifyOptions(t *testing.T) { DryRun: dryRun, Name: releaseName, DisableHooks: disableHooks, - Namespace: namespace, ReuseName: reuseName, } @@ -139,7 +134,7 @@ func TestInstallRelease_VerifyOptions(t *testing.T) { }) 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) } diff --git a/pkg/helm/option.go b/pkg/helm/option.go index 0a476a5ea..245876519 100644 --- a/pkg/helm/option.go +++ b/pkg/helm/option.go @@ -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 // configurable by the helm client user for overriding // the defaults used when running the `helm install` command. diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 0684f4cc0..0c7f4f286 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -35,7 +35,6 @@ import ( extv1beta1 "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -65,18 +64,14 @@ var ErrNoObjectsVisited = goerrors.New("no objects visited") // Client represents a client capable of communicating with the Kubernetes API. type Client struct { cmdutil.Factory - // SchemaCacheDir is the path for loading cached schema. - SchemaCacheDir string - Log func(string, ...interface{}) } // New creates a new Client. func New(config clientcmd.ClientConfig) *Client { return &Client{ - Factory: cmdutil.NewFactory(config), - SchemaCacheDir: clientcmd.RecommendedSchemaFile, - Log: nopLogger, + Factory: cmdutil.NewFactory(config), + Log: nopLogger, } } @@ -89,18 +84,11 @@ type ResourceActorFunc func(*resource.Info) error // // Namespace will set the namespace. 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 { 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)) if err := perform(infos, createResource); err != nil { return err @@ -111,13 +99,21 @@ func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shoul 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 { return c.NewBuilder(). Internal(). ContinueOnError(). Schema(c.validator()). - NamespaceParam(namespace). + NamespaceParam(c.namespace()). DefaultNamespace(). + RequireNamespace(). Stream(reader, ""). Flatten(). Do() @@ -138,8 +134,9 @@ func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result, result, err := c.NewBuilder(). Unstructured(). ContinueOnError(). - NamespaceParam(namespace). + NamespaceParam(c.namespace()). DefaultNamespace(). + RequireNamespace(). Stream(reader, ""). Flatten(). Do().Infos() @@ -393,12 +390,12 @@ func deleteResource(c *Client, info *resource.Info) error { 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) if err != nil { 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 { 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 - versionedObject, err := mapping.ConvertToVersion(target, mapping.GroupVersionKind.GroupVersion()) + versionedObject, err := target.Versioned() // Unstructured objects, such as CRDs, may not have an not registered error // 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 { - patch, patchType, err := createPatch(target.Mapping, target.Object, currentObj) + patch, patchType, err := createPatch(target, currentObj) if err != nil { return fmt.Errorf("failed to create patch: %s", err) } diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 47049810a..97dcd3b90 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -123,14 +123,10 @@ type testClient struct { func newTestClient() *testClient { tf := cmdtesting.NewTestFactory() - c := &Client{ - Factory: tf, - Log: nopLogger, - } - return &testClient{ - Client: c, - TestFactory: tf, - } + tf.Namespace = core.NamespaceDefault + + c := &Client{Factory: tf, Log: nopLogger} + return &testClient{Client: c, TestFactory: tf} } func TestUpdate(t *testing.T) { @@ -181,6 +177,7 @@ func TestUpdate(t *testing.T) { } c := newTestClient() + tf.Namespace = core.NamespaceDefault reaper := &fakeReaper{} rf := &fakeReaperFactory{Factory: tf, reaper: reaper} c.Client.Factory = rf @@ -309,20 +306,17 @@ func TestGet(t *testing.T) { func TestPerform(t *testing.T) { tests := []struct { name string - namespace string reader io.Reader count int err bool errMessage string }{ { - name: "Valid input", - namespace: "test", - reader: strings.NewReader(guestbookManifest), - count: 6, + name: "Valid input", + reader: strings.NewReader(guestbookManifest), + count: 6, }, { name: "Empty manifests", - namespace: "test", reader: strings.NewReader(""), err: true, errMessage: "no objects visited", @@ -335,16 +329,12 @@ func TestPerform(t *testing.T) { fn := func(info *resource.Info) error { results = append(results, info) - - if info.Namespace != tt.namespace { - t.Errorf("expected namespace to be '%s', got %s", tt.namespace, info.Namespace) - } return nil } c := newTestClient() 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 { t.Errorf("Error while building manifests: %v", err) } diff --git a/pkg/kube/config.go b/pkg/kube/config.go index b6560486e..5538d6008 100644 --- a/pkg/kube/config.go +++ b/pkg/kube/config.go @@ -16,17 +16,21 @@ limitations under the License. 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. -func GetConfig(context string) clientcmd.ClientConfig { +func GetConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { rules := clientcmd.NewDefaultClientConfigLoadingRules() 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} + 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) } diff --git a/pkg/kube/namespace.go b/pkg/kube/namespace.go deleted file mode 100644 index 9d2793d87..000000000 --- a/pkg/kube/namespace.go +++ /dev/null @@ -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 -} diff --git a/pkg/kube/namespace_test.go b/pkg/kube/namespace_test.go deleted file mode 100644 index eb96557d0..000000000 --- a/pkg/kube/namespace_test.go +++ /dev/null @@ -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) - } -} diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go index e475b59f6..38545039c 100644 --- a/pkg/plugin/plugin.go +++ b/pkg/plugin/plugin.go @@ -182,8 +182,6 @@ func SetupPluginEnv(settings helm_env.EnvSettings, "HELM_PATH_CACHE": settings.Home.Cache(), "HELM_PATH_LOCAL_REPOSITORY": settings.Home.LocalRepository(), "HELM_PATH_STARTER": settings.Home.Starters(), - - "TILLER_NAMESPACE": settings.TillerNamespace, } { os.Setenv(key, val) } diff --git a/pkg/storage/driver/secrets.go b/pkg/storage/driver/secrets.go index db4e091da..29980646f 100644 --- a/pkg/storage/driver/secrets.go +++ b/pkg/storage/driver/secrets.go @@ -253,6 +253,7 @@ func newSecretsObject(key string, rls *rspb.Release, lbs labels) (*v1.Secret, er Name: key, Labels: lbs.toMap(), }, + Type: "helm.sh/release", Data: map[string][]byte{"release": []byte(s)}, }, nil } diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index d99f2393c..eaae7e9e5 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -37,9 +37,6 @@ import ( "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. const GoTplEngine = "gotpl" diff --git a/pkg/tiller/release_list.go b/pkg/tiller/release_list.go index 5f1a3312e..e1a902554 100644 --- a/pkg/tiller/release_list.go +++ b/pkg/tiller/release_list.go @@ -42,10 +42,6 @@ func (s *ReleaseServer) ListReleases(req *hapi.ListReleasesRequest) ([]*release. return nil, err } - if req.Namespace != "" { - rels = filterByNamespace(req.Namespace, rels) - } - if len(req.Filter) != 0 { rels, err = filterReleases(req.Filter, rels) if err != nil { @@ -72,16 +68,6 @@ func (s *ReleaseServer) ListReleases(req *hapi.ListReleasesRequest) ([]*release. 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) { preg, err := regexp.Compile(filter) if err != nil { diff --git a/pkg/tiller/release_list_test.go b/pkg/tiller/release_list_test.go index e6ccbe5c8..9df2256ba 100644 --- a/pkg/tiller/release_list_test.go +++ b/pkg/tiller/release_list_test.go @@ -189,45 +189,3 @@ func TestListReleasesFilter(t *testing.T) { 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)) - } -}