github.com/strongmonkey/helm@v2.7.2+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 _, 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 }