github.com/migueleliasweb/helm@v2.6.1+incompatible/cmd/helm/upgrade.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"strings"
    23  
    24  	"github.com/spf13/cobra"
    25  
    26  	"k8s.io/helm/pkg/chartutil"
    27  	"k8s.io/helm/pkg/helm"
    28  	"k8s.io/helm/pkg/storage/driver"
    29  )
    30  
    31  const upgradeDesc = `
    32  This command upgrades a release to a new version of a chart.
    33  
    34  The upgrade arguments must be a release and chart. The chart
    35  argument can be either: a chart reference('stable/mariadb'), a path to a chart directory,
    36  a packaged chart, or a fully qualified URL. For chart references, the latest
    37  version will be specified unless the '--version' flag is set.
    38  
    39  To override values in a chart, use either the '--values' flag and pass in a file
    40  or use the '--set' flag and pass configuration from the command line.
    41  
    42  You can specify the '--values'/'-f' flag multiple times. The priority will be given to the
    43  last (right-most) file specified. For example, if both myvalues.yaml and override.yaml
    44  contained a key called 'Test', the value set in override.yaml would take precedence:
    45  
    46  	$ helm upgrade -f myvalues.yaml -f override.yaml redis ./redis
    47  
    48  You can specify the '--set' flag multiple times. The priority will be given to the
    49  last (right-most) set specified. For example, if both 'bar' and 'newbar' values are
    50  set for a key called 'foo', the 'newbar' value would take precedence:
    51  
    52  	$ helm upgrade --set foo=bar --set foo=newbar redis ./redis
    53  `
    54  
    55  type upgradeCmd struct {
    56  	release      string
    57  	chart        string
    58  	out          io.Writer
    59  	client       helm.Interface
    60  	dryRun       bool
    61  	recreate     bool
    62  	force        bool
    63  	disableHooks bool
    64  	valueFiles   valueFiles
    65  	values       []string
    66  	verify       bool
    67  	keyring      string
    68  	install      bool
    69  	namespace    string
    70  	version      string
    71  	timeout      int64
    72  	resetValues  bool
    73  	reuseValues  bool
    74  	wait         bool
    75  	repoURL      string
    76  	devel        bool
    77  
    78  	certFile string
    79  	keyFile  string
    80  	caFile   string
    81  }
    82  
    83  func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
    84  
    85  	upgrade := &upgradeCmd{
    86  		out:    out,
    87  		client: client,
    88  	}
    89  
    90  	cmd := &cobra.Command{
    91  		Use:     "upgrade [RELEASE] [CHART]",
    92  		Short:   "upgrade a release",
    93  		Long:    upgradeDesc,
    94  		PreRunE: setupConnection,
    95  		RunE: func(cmd *cobra.Command, args []string) error {
    96  			if err := checkArgsLength(len(args), "release name", "chart path"); err != nil {
    97  				return err
    98  			}
    99  
   100  			if upgrade.version == "" && upgrade.devel {
   101  				debug("setting version to >0.0.0-a")
   102  				upgrade.version = ">0.0.0-a"
   103  			}
   104  
   105  			upgrade.release = args[0]
   106  			upgrade.chart = args[1]
   107  			upgrade.client = ensureHelmClient(upgrade.client)
   108  
   109  			return upgrade.run()
   110  		},
   111  	}
   112  
   113  	f := cmd.Flags()
   114  	f.VarP(&upgrade.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
   115  	f.BoolVar(&upgrade.dryRun, "dry-run", false, "simulate an upgrade")
   116  	f.BoolVar(&upgrade.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
   117  	f.BoolVar(&upgrade.force, "force", false, "force resource update through delete/recreate if needed")
   118  	f.StringArrayVar(&upgrade.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
   119  	f.BoolVar(&upgrade.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks")
   120  	f.BoolVar(&upgrade.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks")
   121  	f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading")
   122  	f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys")
   123  	f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
   124  	f.StringVar(&upgrade.namespace, "namespace", "", "namespace to install the release into (only used if --install is set). Defaults to the current kube config namespace")
   125  	f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
   126  	f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
   127  	f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
   128  	f.BoolVar(&upgrade.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values, and merge in any new values. If '--reset-values' is specified, this is ignored.")
   129  	f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
   130  	f.StringVar(&upgrade.repoURL, "repo", "", "chart repository url where to locate the requested chart")
   131  	f.StringVar(&upgrade.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
   132  	f.StringVar(&upgrade.keyFile, "key-file", "", "identify HTTPS client using this SSL key file")
   133  	f.StringVar(&upgrade.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
   134  	f.BoolVar(&upgrade.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-a'. If --version is set, this is ignored.")
   135  
   136  	f.MarkDeprecated("disable-hooks", "use --no-hooks instead")
   137  
   138  	return cmd
   139  }
   140  
   141  func (u *upgradeCmd) run() error {
   142  	chartPath, err := locateChartPath(u.repoURL, u.chart, u.version, u.verify, u.keyring, u.certFile, u.keyFile, u.caFile)
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	if u.install {
   148  		// If a release does not exist, install it. If another error occurs during
   149  		// the check, ignore the error and continue with the upgrade.
   150  		//
   151  		// The returned error is a grpc.rpcError that wraps the message from the original error.
   152  		// So we're stuck doing string matching against the wrapped error, which is nested somewhere
   153  		// inside of the grpc.rpcError message.
   154  		_, err := u.client.ReleaseHistory(u.release, helm.WithMaxHistory(1))
   155  		if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) {
   156  			fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release)
   157  			ic := &installCmd{
   158  				chartPath:    chartPath,
   159  				client:       u.client,
   160  				out:          u.out,
   161  				name:         u.release,
   162  				valueFiles:   u.valueFiles,
   163  				dryRun:       u.dryRun,
   164  				verify:       u.verify,
   165  				disableHooks: u.disableHooks,
   166  				keyring:      u.keyring,
   167  				values:       u.values,
   168  				namespace:    u.namespace,
   169  				timeout:      u.timeout,
   170  				wait:         u.wait,
   171  			}
   172  			return ic.run()
   173  		}
   174  	}
   175  
   176  	rawVals, err := vals(u.valueFiles, u.values)
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	// Check chart requirements to make sure all dependencies are present in /charts
   182  	if ch, err := chartutil.Load(chartPath); err == nil {
   183  		if req, err := chartutil.LoadRequirements(ch); err == nil {
   184  			if err := checkDependencies(ch, req); err != nil {
   185  				return err
   186  			}
   187  		} else if err != chartutil.ErrRequirementsNotFound {
   188  			return fmt.Errorf("cannot load requirements: %v", err)
   189  		}
   190  	} else {
   191  		return prettyError(err)
   192  	}
   193  
   194  	resp, err := u.client.UpdateRelease(
   195  		u.release,
   196  		chartPath,
   197  		helm.UpdateValueOverrides(rawVals),
   198  		helm.UpgradeDryRun(u.dryRun),
   199  		helm.UpgradeRecreate(u.recreate),
   200  		helm.UpgradeForce(u.force),
   201  		helm.UpgradeDisableHooks(u.disableHooks),
   202  		helm.UpgradeTimeout(u.timeout),
   203  		helm.ResetValues(u.resetValues),
   204  		helm.ReuseValues(u.reuseValues),
   205  		helm.UpgradeWait(u.wait))
   206  	if err != nil {
   207  		return fmt.Errorf("UPGRADE FAILED: %v", prettyError(err))
   208  	}
   209  
   210  	if settings.Debug {
   211  		printRelease(u.out, resp.Release)
   212  	}
   213  
   214  	fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release)
   215  
   216  	// Print the status like status command does
   217  	status, err := u.client.ReleaseStatus(u.release)
   218  	if err != nil {
   219  		return prettyError(err)
   220  	}
   221  	PrintStatus(u.out, status)
   222  
   223  	return nil
   224  }