github.com/valdemarpavesi/helm@v2.9.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, to force string 41 values, use '--set-string'. 42 43 You can specify the '--values'/'-f' flag multiple times. The priority will be given to the 44 last (right-most) file specified. For example, if both myvalues.yaml and override.yaml 45 contained a key called 'Test', the value set in override.yaml would take precedence: 46 47 $ helm upgrade -f myvalues.yaml -f override.yaml redis ./redis 48 49 You can specify the '--set' flag multiple times. The priority will be given to the 50 last (right-most) set specified. For example, if both 'bar' and 'newbar' values are 51 set for a key called 'foo', the 'newbar' value would take precedence: 52 53 $ helm upgrade --set foo=bar --set foo=newbar redis ./redis 54 ` 55 56 type upgradeCmd struct { 57 release string 58 chart string 59 out io.Writer 60 client helm.Interface 61 dryRun bool 62 recreate bool 63 force bool 64 disableHooks bool 65 valueFiles valueFiles 66 values []string 67 stringValues []string 68 verify bool 69 keyring string 70 install bool 71 namespace string 72 version string 73 timeout int64 74 resetValues bool 75 reuseValues bool 76 wait bool 77 repoURL string 78 username string 79 password string 80 devel bool 81 82 certFile string 83 keyFile string 84 caFile string 85 } 86 87 func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { 88 89 upgrade := &upgradeCmd{ 90 out: out, 91 client: client, 92 } 93 94 cmd := &cobra.Command{ 95 Use: "upgrade [RELEASE] [CHART]", 96 Short: "upgrade a release", 97 Long: upgradeDesc, 98 PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, 99 RunE: func(cmd *cobra.Command, args []string) error { 100 if err := checkArgsLength(len(args), "release name", "chart path"); err != nil { 101 return err 102 } 103 104 if upgrade.version == "" && upgrade.devel { 105 debug("setting version to >0.0.0-0") 106 upgrade.version = ">0.0.0-0" 107 } 108 109 upgrade.release = args[0] 110 upgrade.chart = args[1] 111 upgrade.client = ensureHelmClient(upgrade.client) 112 113 return upgrade.run() 114 }, 115 } 116 117 f := cmd.Flags() 118 f.VarP(&upgrade.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") 119 f.BoolVar(&upgrade.dryRun, "dry-run", false, "simulate an upgrade") 120 f.BoolVar(&upgrade.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable") 121 f.BoolVar(&upgrade.force, "force", false, "force resource update through delete/recreate if needed") 122 f.StringArrayVar(&upgrade.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") 123 f.StringArrayVar(&upgrade.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") 124 f.BoolVar(&upgrade.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks") 125 f.BoolVar(&upgrade.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks") 126 f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading") 127 f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys") 128 f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install") 129 f.StringVar(&upgrade.namespace, "namespace", "", "namespace to install the release into (only used if --install is set). Defaults to the current kube config namespace") 130 f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used") 131 f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") 132 f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart") 133 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.") 134 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") 135 f.StringVar(&upgrade.repoURL, "repo", "", "chart repository url where to locate the requested chart") 136 f.StringVar(&upgrade.username, "username", "", "chart repository username where to locate the requested chart") 137 f.StringVar(&upgrade.password, "password", "", "chart repository password where to locate the requested chart") 138 f.StringVar(&upgrade.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") 139 f.StringVar(&upgrade.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") 140 f.StringVar(&upgrade.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") 141 f.BoolVar(&upgrade.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") 142 143 f.MarkDeprecated("disable-hooks", "use --no-hooks instead") 144 145 return cmd 146 } 147 148 func (u *upgradeCmd) run() error { 149 chartPath, err := locateChartPath(u.repoURL, u.username, u.password, u.chart, u.version, u.verify, u.keyring, u.certFile, u.keyFile, u.caFile) 150 if err != nil { 151 return err 152 } 153 154 if u.install { 155 // If a release does not exist, install it. If another error occurs during 156 // the check, ignore the error and continue with the upgrade. 157 // 158 // The returned error is a grpc.rpcError that wraps the message from the original error. 159 // So we're stuck doing string matching against the wrapped error, which is nested somewhere 160 // inside of the grpc.rpcError message. 161 releaseHistory, err := u.client.ReleaseHistory(u.release, helm.WithMaxHistory(1)) 162 163 if err == nil { 164 if u.namespace == "" { 165 u.namespace = defaultNamespace() 166 } 167 previousReleaseNamespace := releaseHistory.Releases[0].Namespace 168 if previousReleaseNamespace != u.namespace { 169 fmt.Fprintf(u.out, 170 "WARNING: Namespace %q doesn't match with previous. Release will be deployed to %s\n", 171 u.namespace, previousReleaseNamespace, 172 ) 173 } 174 } 175 176 if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) { 177 fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release) 178 ic := &installCmd{ 179 chartPath: chartPath, 180 client: u.client, 181 out: u.out, 182 name: u.release, 183 valueFiles: u.valueFiles, 184 dryRun: u.dryRun, 185 verify: u.verify, 186 disableHooks: u.disableHooks, 187 keyring: u.keyring, 188 values: u.values, 189 stringValues: u.stringValues, 190 namespace: u.namespace, 191 timeout: u.timeout, 192 wait: u.wait, 193 } 194 return ic.run() 195 } 196 } 197 198 rawVals, err := vals(u.valueFiles, u.values, u.stringValues) 199 if err != nil { 200 return err 201 } 202 203 // Check chart requirements to make sure all dependencies are present in /charts 204 if ch, err := chartutil.Load(chartPath); err == nil { 205 if req, err := chartutil.LoadRequirements(ch); err == nil { 206 if err := checkDependencies(ch, req); err != nil { 207 return err 208 } 209 } else if err != chartutil.ErrRequirementsNotFound { 210 return fmt.Errorf("cannot load requirements: %v", err) 211 } 212 } else { 213 return prettyError(err) 214 } 215 216 resp, err := u.client.UpdateRelease( 217 u.release, 218 chartPath, 219 helm.UpdateValueOverrides(rawVals), 220 helm.UpgradeDryRun(u.dryRun), 221 helm.UpgradeRecreate(u.recreate), 222 helm.UpgradeForce(u.force), 223 helm.UpgradeDisableHooks(u.disableHooks), 224 helm.UpgradeTimeout(u.timeout), 225 helm.ResetValues(u.resetValues), 226 helm.ReuseValues(u.reuseValues), 227 helm.UpgradeWait(u.wait)) 228 if err != nil { 229 return fmt.Errorf("UPGRADE FAILED: %v", prettyError(err)) 230 } 231 232 if settings.Debug { 233 printRelease(u.out, resp.Release) 234 } 235 236 fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release) 237 238 // Print the status like status command does 239 status, err := u.client.ReleaseStatus(u.release) 240 if err != nil { 241 return prettyError(err) 242 } 243 PrintStatus(u.out, status) 244 245 return nil 246 }