...

Source file src/helm.sh/helm/v3/pkg/action/pull.go

Documentation: helm.sh/helm/v3/pkg/action

     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  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/pkg/errors"
    26  
    27  	"helm.sh/helm/v3/pkg/chartutil"
    28  	"helm.sh/helm/v3/pkg/cli"
    29  	"helm.sh/helm/v3/pkg/downloader"
    30  	"helm.sh/helm/v3/pkg/getter"
    31  	"helm.sh/helm/v3/pkg/registry"
    32  	"helm.sh/helm/v3/pkg/repo"
    33  )
    34  
    35  // Pull is the action for checking a given release's information.
    36  //
    37  // It provides the implementation of 'helm pull'.
    38  type Pull struct {
    39  	ChartPathOptions
    40  
    41  	Settings *cli.EnvSettings // TODO: refactor this out of pkg/action
    42  
    43  	Devel       bool
    44  	Untar       bool
    45  	VerifyLater bool
    46  	UntarDir    string
    47  	DestDir     string
    48  	cfg         *Configuration
    49  }
    50  
    51  type PullOpt func(*Pull)
    52  
    53  func WithConfig(cfg *Configuration) PullOpt {
    54  	return func(p *Pull) {
    55  		p.cfg = cfg
    56  	}
    57  }
    58  
    59  // NewPull creates a new Pull object.
    60  func NewPull() *Pull {
    61  	return NewPullWithOpts()
    62  }
    63  
    64  // NewPullWithOpts creates a new pull, with configuration options.
    65  func NewPullWithOpts(opts ...PullOpt) *Pull {
    66  	p := &Pull{}
    67  	for _, fn := range opts {
    68  		fn(p)
    69  	}
    70  
    71  	return p
    72  }
    73  
    74  // SetRegistryClient sets the registry client on the pull configuration object.
    75  func (p *Pull) SetRegistryClient(client *registry.Client) {
    76  	p.cfg.RegistryClient = client
    77  }
    78  
    79  // Run executes 'helm pull' against the given release.
    80  func (p *Pull) Run(chartRef string) (string, error) {
    81  	var out strings.Builder
    82  
    83  	c := downloader.ChartDownloader{
    84  		Out:     &out,
    85  		Keyring: p.Keyring,
    86  		Verify:  downloader.VerifyNever,
    87  		Getters: getter.All(p.Settings),
    88  		Options: []getter.Option{
    89  			getter.WithBasicAuth(p.Username, p.Password),
    90  			getter.WithPassCredentialsAll(p.PassCredentialsAll),
    91  			getter.WithTLSClientConfig(p.CertFile, p.KeyFile, p.CaFile),
    92  			getter.WithInsecureSkipVerifyTLS(p.InsecureSkipTLSverify),
    93  			getter.WithPlainHTTP(p.PlainHTTP),
    94  		},
    95  		RegistryClient:   p.cfg.RegistryClient,
    96  		RepositoryConfig: p.Settings.RepositoryConfig,
    97  		RepositoryCache:  p.Settings.RepositoryCache,
    98  	}
    99  
   100  	if registry.IsOCI(chartRef) {
   101  		c.Options = append(c.Options,
   102  			getter.WithRegistryClient(p.cfg.RegistryClient))
   103  		c.RegistryClient = p.cfg.RegistryClient
   104  	}
   105  
   106  	if p.Verify {
   107  		c.Verify = downloader.VerifyAlways
   108  	} else if p.VerifyLater {
   109  		c.Verify = downloader.VerifyLater
   110  	}
   111  
   112  	// If untar is set, we fetch to a tempdir, then untar and copy after
   113  	// verification.
   114  	dest := p.DestDir
   115  	if p.Untar {
   116  		var err error
   117  		dest, err = os.MkdirTemp("", "helm-")
   118  		if err != nil {
   119  			return out.String(), errors.Wrap(err, "failed to untar")
   120  		}
   121  		defer os.RemoveAll(dest)
   122  	}
   123  
   124  	if p.RepoURL != "" {
   125  		chartURL, err := repo.FindChartInAuthAndTLSAndPassRepoURL(p.RepoURL, p.Username, p.Password, chartRef, p.Version, p.CertFile, p.KeyFile, p.CaFile, p.InsecureSkipTLSverify, p.PassCredentialsAll, getter.All(p.Settings))
   126  		if err != nil {
   127  			return out.String(), err
   128  		}
   129  		chartRef = chartURL
   130  	}
   131  
   132  	saved, v, err := c.DownloadTo(chartRef, p.Version, dest)
   133  	if err != nil {
   134  		return out.String(), err
   135  	}
   136  
   137  	if p.Verify {
   138  		for name := range v.SignedBy.Identities {
   139  			fmt.Fprintf(&out, "Signed by: %v\n", name)
   140  		}
   141  		fmt.Fprintf(&out, "Using Key With Fingerprint: %X\n", v.SignedBy.PrimaryKey.Fingerprint)
   142  		fmt.Fprintf(&out, "Chart Hash Verified: %s\n", v.FileHash)
   143  	}
   144  
   145  	// After verification, untar the chart into the requested directory.
   146  	if p.Untar {
   147  		ud := p.UntarDir
   148  		if !filepath.IsAbs(ud) {
   149  			ud = filepath.Join(p.DestDir, ud)
   150  		}
   151  		// Let udCheck to check conflict file/dir without replacing ud when untarDir is the current directory(.).
   152  		udCheck := ud
   153  		if udCheck == "." {
   154  			_, udCheck = filepath.Split(chartRef)
   155  		} else {
   156  			_, chartName := filepath.Split(chartRef)
   157  			udCheck = filepath.Join(udCheck, chartName)
   158  		}
   159  
   160  		if _, err := os.Stat(udCheck); err != nil {
   161  			if err := os.MkdirAll(udCheck, 0755); err != nil {
   162  				return out.String(), errors.Wrap(err, "failed to untar (mkdir)")
   163  			}
   164  
   165  		} else {
   166  			return out.String(), errors.Errorf("failed to untar: a file or directory with the name %s already exists", udCheck)
   167  		}
   168  
   169  		return out.String(), chartutil.ExpandFile(ud, saved)
   170  	}
   171  	return out.String(), nil
   172  }
   173  

View as plain text