github.com/amundsenjunior/helm@v2.8.0-rc.1.0.20180119233529-2b92431476e1+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-0") 102 upgrade.version = ">0.0.0-0" 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 or a URL(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-0'. 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 releaseHistory, err := u.client.ReleaseHistory(u.release, helm.WithMaxHistory(1)) 155 156 if err == nil { 157 previousReleaseNamespace := releaseHistory.Releases[0].Namespace 158 if previousReleaseNamespace != u.namespace { 159 fmt.Fprintf(u.out, "WARNING: Namespace doesn't match with previous. Release will be deployed to %s\n", previousReleaseNamespace) 160 } 161 } 162 163 if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) { 164 fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release) 165 ic := &installCmd{ 166 chartPath: chartPath, 167 client: u.client, 168 out: u.out, 169 name: u.release, 170 valueFiles: u.valueFiles, 171 dryRun: u.dryRun, 172 verify: u.verify, 173 disableHooks: u.disableHooks, 174 keyring: u.keyring, 175 values: u.values, 176 namespace: u.namespace, 177 timeout: u.timeout, 178 wait: u.wait, 179 } 180 return ic.run() 181 } 182 } 183 184 rawVals, err := vals(u.valueFiles, u.values) 185 if err != nil { 186 return err 187 } 188 189 // Check chart requirements to make sure all dependencies are present in /charts 190 if ch, err := chartutil.Load(chartPath); err == nil { 191 if req, err := chartutil.LoadRequirements(ch); err == nil { 192 if err := checkDependencies(ch, req); err != nil { 193 return err 194 } 195 } else if err != chartutil.ErrRequirementsNotFound { 196 return fmt.Errorf("cannot load requirements: %v", err) 197 } 198 } else { 199 return prettyError(err) 200 } 201 202 resp, err := u.client.UpdateRelease( 203 u.release, 204 chartPath, 205 helm.UpdateValueOverrides(rawVals), 206 helm.UpgradeDryRun(u.dryRun), 207 helm.UpgradeRecreate(u.recreate), 208 helm.UpgradeForce(u.force), 209 helm.UpgradeDisableHooks(u.disableHooks), 210 helm.UpgradeTimeout(u.timeout), 211 helm.ResetValues(u.resetValues), 212 helm.ReuseValues(u.reuseValues), 213 helm.UpgradeWait(u.wait)) 214 if err != nil { 215 return fmt.Errorf("UPGRADE FAILED: %v", prettyError(err)) 216 } 217 218 if settings.Debug { 219 printRelease(u.out, resp.Release) 220 } 221 222 fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release) 223 224 // Print the status like status command does 225 status, err := u.client.ReleaseStatus(u.release) 226 if err != nil { 227 return prettyError(err) 228 } 229 PrintStatus(u.out, status) 230 231 return nil 232 }