github.com/defensepoint-snyk-test/helm-new@v0.0.0-20211130153739-c57ea64d6603/cmd/helm/package.go (about) 1 /* 2 Copyright The Helm Authors. 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 "errors" 21 "fmt" 22 "io" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "syscall" 27 28 "github.com/Masterminds/semver" 29 "github.com/spf13/cobra" 30 "golang.org/x/crypto/ssh/terminal" 31 32 "k8s.io/helm/pkg/chartutil" 33 "k8s.io/helm/pkg/downloader" 34 "k8s.io/helm/pkg/getter" 35 "k8s.io/helm/pkg/helm/helmpath" 36 "k8s.io/helm/pkg/proto/hapi/chart" 37 "k8s.io/helm/pkg/provenance" 38 "k8s.io/helm/pkg/renderutil" 39 "k8s.io/helm/pkg/repo" 40 ) 41 42 const packageDesc = ` 43 This command packages a chart into a versioned chart archive file. If a path 44 is given, this will look at that path for a chart (which must contain a 45 Chart.yaml file) and then package that directory. 46 47 If no path is given, this will look in the present working directory for a 48 Chart.yaml file, and (if found) build the current directory into a chart. 49 50 Versioned chart archives are used by Helm package repositories. 51 ` 52 53 type packageCmd struct { 54 save bool 55 sign bool 56 path string 57 key string 58 keyring string 59 version string 60 appVersion string 61 destination string 62 dependencyUpdate bool 63 64 out io.Writer 65 home helmpath.Home 66 } 67 68 func newPackageCmd(out io.Writer) *cobra.Command { 69 pkg := &packageCmd{out: out} 70 71 cmd := &cobra.Command{ 72 Use: "package [flags] [CHART_PATH] [...]", 73 Short: "package a chart directory into a chart archive", 74 Long: packageDesc, 75 RunE: func(cmd *cobra.Command, args []string) error { 76 pkg.home = settings.Home 77 if len(args) == 0 { 78 return fmt.Errorf("need at least one argument, the path to the chart") 79 } 80 if pkg.sign { 81 if pkg.key == "" { 82 return errors.New("--key is required for signing a package") 83 } 84 if pkg.keyring == "" { 85 return errors.New("--keyring is required for signing a package") 86 } 87 } 88 for i := 0; i < len(args); i++ { 89 pkg.path = args[i] 90 if err := pkg.run(); err != nil { 91 return err 92 } 93 } 94 return nil 95 }, 96 } 97 98 f := cmd.Flags() 99 f.BoolVar(&pkg.save, "save", true, "save packaged chart to local chart repository") 100 f.BoolVar(&pkg.sign, "sign", false, "use a PGP private key to sign this package") 101 f.StringVar(&pkg.key, "key", "", "name of the key to use when signing. Used if --sign is true") 102 f.StringVar(&pkg.keyring, "keyring", defaultKeyring(), "location of a public keyring") 103 f.StringVar(&pkg.version, "version", "", "set the version on the chart to this semver version") 104 f.StringVar(&pkg.appVersion, "app-version", "", "set the appVersion on the chart to this version") 105 f.StringVarP(&pkg.destination, "destination", "d", ".", "location to write the chart.") 106 f.BoolVarP(&pkg.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`) 107 108 return cmd 109 } 110 111 func (p *packageCmd) run() error { 112 path, err := filepath.Abs(p.path) 113 if err != nil { 114 return err 115 } 116 117 if p.dependencyUpdate { 118 downloadManager := &downloader.Manager{ 119 Out: p.out, 120 ChartPath: path, 121 HelmHome: settings.Home, 122 Keyring: p.keyring, 123 Getters: getter.All(settings), 124 Debug: settings.Debug, 125 } 126 127 if err := downloadManager.Update(); err != nil { 128 return err 129 } 130 } 131 132 ch, err := chartutil.LoadDir(path) 133 if err != nil { 134 return err 135 } 136 137 // If version is set, modify the version. 138 if len(p.version) != 0 { 139 if err := setVersion(ch, p.version); err != nil { 140 return err 141 } 142 debug("Setting version to %s", p.version) 143 } 144 145 if p.appVersion != "" { 146 ch.Metadata.AppVersion = p.appVersion 147 debug("Setting appVersion to %s", p.appVersion) 148 } 149 150 if filepath.Base(path) != ch.Metadata.Name { 151 return fmt.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Metadata.Name) 152 } 153 154 if reqs, err := chartutil.LoadRequirements(ch); err == nil { 155 if err := renderutil.CheckDependencies(ch, reqs); err != nil { 156 return err 157 } 158 } else { 159 if err != chartutil.ErrRequirementsNotFound { 160 return err 161 } 162 } 163 164 var dest string 165 if p.destination == "." { 166 // Save to the current working directory. 167 dest, err = os.Getwd() 168 if err != nil { 169 return err 170 } 171 } else { 172 // Otherwise save to set destination 173 dest = p.destination 174 } 175 176 name, err := chartutil.Save(ch, dest) 177 if err == nil { 178 fmt.Fprintf(p.out, "Successfully packaged chart and saved it to: %s\n", name) 179 } else { 180 return fmt.Errorf("Failed to save: %s", err) 181 } 182 183 // Save to $HELM_HOME/local directory. This is second, because we don't want 184 // the case where we saved here, but didn't save to the default destination. 185 if p.save { 186 lr := p.home.LocalRepository() 187 if err := repo.AddChartToLocalRepo(ch, lr); err != nil { 188 return err 189 } 190 debug("Successfully saved %s to %s\n", name, lr) 191 } 192 193 if p.sign { 194 err = p.clearsign(name) 195 } 196 197 return err 198 } 199 200 func setVersion(ch *chart.Chart, ver string) error { 201 // Verify that version is a SemVer, and error out if it is not. 202 if _, err := semver.NewVersion(ver); err != nil { 203 return err 204 } 205 206 // Set the version field on the chart. 207 ch.Metadata.Version = ver 208 return nil 209 } 210 211 func (p *packageCmd) clearsign(filename string) error { 212 // Load keyring 213 signer, err := provenance.NewFromKeyring(p.keyring, p.key) 214 if err != nil { 215 return err 216 } 217 218 if err := signer.DecryptKey(passphraseFetcher); err != nil { 219 return err 220 } 221 222 sig, err := signer.ClearSign(filename) 223 if err != nil { 224 return err 225 } 226 227 debug(sig) 228 229 return ioutil.WriteFile(filename+".prov", []byte(sig), 0755) 230 } 231 232 // passphraseFetcher implements provenance.PassphraseFetcher 233 func passphraseFetcher(name string) ([]byte, error) { 234 var passphrase = settings.HelmKeyPassphrase() 235 if passphrase != "" { 236 return []byte(passphrase), nil 237 } 238 239 fmt.Printf("Password for key %q > ", name) 240 pw, err := terminal.ReadPassword(int(syscall.Stdin)) 241 fmt.Println() 242 return pw, err 243 }