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