github.com/uhthomas/helm@v3.0.0-beta.3+incompatible/pkg/action/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 action
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"syscall"
    24  
    25  	"github.com/Masterminds/semver"
    26  	"github.com/pkg/errors"
    27  	"golang.org/x/crypto/ssh/terminal"
    28  
    29  	"helm.sh/helm/pkg/chart"
    30  	"helm.sh/helm/pkg/chart/loader"
    31  	"helm.sh/helm/pkg/chartutil"
    32  	"helm.sh/helm/pkg/provenance"
    33  )
    34  
    35  // Package is the action for packaging a chart.
    36  //
    37  // It provides the implementation of 'helm package'.
    38  type Package struct {
    39  	Sign             bool
    40  	Key              string
    41  	Keyring          string
    42  	Version          string
    43  	AppVersion       string
    44  	Destination      string
    45  	DependencyUpdate bool
    46  
    47  	RepositoryConfig string
    48  	RepositoryCache  string
    49  }
    50  
    51  // NewPackage creates a new Package object with the given configuration.
    52  func NewPackage() *Package {
    53  	return &Package{}
    54  }
    55  
    56  // Run executes 'helm package' against the given chart and returns the path to the packaged chart.
    57  func (p *Package) Run(path string, vals map[string]interface{}) (string, error) {
    58  	ch, err := loader.LoadDir(path)
    59  	if err != nil {
    60  		return "", err
    61  	}
    62  
    63  	combinedVals, err := chartutil.CoalesceValues(ch, vals)
    64  	if err != nil {
    65  		return "", err
    66  	}
    67  	ch.Values = combinedVals
    68  
    69  	// If version is set, modify the version.
    70  	if p.Version != "" {
    71  		if err := setVersion(ch, p.Version); err != nil {
    72  			return "", err
    73  		}
    74  	}
    75  
    76  	if p.AppVersion != "" {
    77  		ch.Metadata.AppVersion = p.AppVersion
    78  	}
    79  
    80  	if reqs := ch.Metadata.Dependencies; reqs != nil {
    81  		if err := CheckDependencies(ch, reqs); err != nil {
    82  			return "", err
    83  		}
    84  	}
    85  
    86  	var dest string
    87  	if p.Destination == "." {
    88  		// Save to the current working directory.
    89  		dest, err = os.Getwd()
    90  		if err != nil {
    91  			return "", err
    92  		}
    93  	} else {
    94  		// Otherwise save to set destination
    95  		dest = p.Destination
    96  	}
    97  
    98  	name, err := chartutil.Save(ch, dest)
    99  	if err != nil {
   100  		return "", errors.Wrap(err, "failed to save")
   101  	}
   102  
   103  	if p.Sign {
   104  		err = p.Clearsign(name)
   105  	}
   106  
   107  	return name, err
   108  }
   109  
   110  func setVersion(ch *chart.Chart, ver string) error {
   111  	// Verify that version is a Version, and error out if it is not.
   112  	if _, err := semver.NewVersion(ver); err != nil {
   113  		return err
   114  	}
   115  
   116  	// Set the version field on the chart.
   117  	ch.Metadata.Version = ver
   118  	return nil
   119  }
   120  
   121  func (p *Package) Clearsign(filename string) error {
   122  	// Load keyring
   123  	signer, err := provenance.NewFromKeyring(p.Keyring, p.Key)
   124  	if err != nil {
   125  		return err
   126  	}
   127  
   128  	if err := signer.DecryptKey(promptUser); err != nil {
   129  		return err
   130  	}
   131  
   132  	sig, err := signer.ClearSign(filename)
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	return ioutil.WriteFile(filename+".prov", []byte(sig), 0644)
   138  }
   139  
   140  // promptUser implements provenance.PassphraseFetcher
   141  func promptUser(name string) ([]byte, error) {
   142  	fmt.Printf("Password for key %q >  ", name)
   143  	pw, err := terminal.ReadPassword(int(syscall.Stdin))
   144  	fmt.Println()
   145  	return pw, err
   146  }