From 694cf61aacba6bc4ed59a65d23acd20f6c8b95bd Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Thu, 20 Feb 2020 11:56:03 -0800 Subject: [PATCH] feat(install): introduce --create-namespace Signed-off-by: Matthew Fisher --- cmd/helm/install.go | 1 + cmd/helm/upgrade.go | 3 +++ pkg/action/install.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/cmd/helm/install.go b/cmd/helm/install.go index ec2c75a12..719dc9014 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -136,6 +136,7 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } func addInstallFlags(f *pflag.FlagSet, client *action.Install, valueOpts *values.Options) { + f.BoolVar(&client.CreateNamespace, "create-namespace", false, "create the release namespace if not present") f.BoolVar(&client.DryRun, "dry-run", false, "simulate an install") f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install") f.BoolVar(&client.Replace, "replace", false, "re-use the given name, only if that name is a deleted release which remains in the history. This is unsafe in production") diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 119d79f8f..dea866e4d 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -65,6 +65,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { client := action.NewUpgrade(cfg) valueOpts := &values.Options{} var outfmt output.Format + var createNamespace bool cmd := &cobra.Command{ Use: "upgrade [RELEASE] [CHART]", @@ -100,6 +101,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", args[0]) } instClient := action.NewInstall(cfg) + instClient.CreateNamespace = createNamespace instClient.ChartPathOptions = client.ChartPathOptions instClient.DryRun = client.DryRun instClient.DisableHooks = client.DisableHooks @@ -159,6 +161,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { }) f := cmd.Flags() + f.BoolVar(&createNamespace, "create-namespace", false, "if --install is set, create the release namespace if not present") f.BoolVarP(&client.Install, "install", "i", false, "if a release by this name doesn't already exist, run an install") f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored") f.BoolVar(&client.DryRun, "dry-run", false, "simulate an upgrade") diff --git a/pkg/action/install.go b/pkg/action/install.go index 79abfae33..e7b481d47 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -29,8 +29,11 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/resource" + "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chartutil" @@ -69,6 +72,7 @@ type Install struct { ChartPathOptions ClientOnly bool + CreateNamespace bool DryRun bool DisableHooks bool Replace bool @@ -265,6 +269,32 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release. return rel, nil } + if i.CreateNamespace { + ns := &v1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: i.Namespace, + Labels: map[string]string{ + "name": i.Namespace, + }, + }, + } + buf, err := yaml.Marshal(ns) + if err != nil { + return nil, err + } + resourceList, err := i.cfg.KubeClient.Build(bytes.NewBuffer(buf), true) + if err != nil { + return nil, err + } + if _, err := i.cfg.KubeClient.Create(resourceList); err != nil && !apierrors.IsAlreadyExists(err) { + return nil, err + } + } + // If Replace is true, we need to supercede the last release. if i.Replace { if err := i.replaceRelease(rel); err != nil {