| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | Copyright The Helm Authors. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | You may obtain a copy of the License at | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | See the License for the specific language governing permissions and | 
					
						
							|  |  |  | limitations under the License. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package action | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2021-07-26 08:04:58 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2023-03-22 21:31:16 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2021-06-12 02:36:55 +08:00
										 |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-01-08 19:29:23 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	"text/template" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 01:42:59 +08:00
										 |  |  | 	"github.com/Masterminds/sprig/v3" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2020-02-21 03:56:03 +08:00
										 |  |  | 	v1 "k8s.io/api/core/v1" | 
					
						
							| 
									
										
										
										
											2019-08-17 06:26:09 +08:00
										 |  |  | 	apierrors "k8s.io/apimachinery/pkg/api/errors" | 
					
						
							| 
									
										
										
										
											2023-03-08 01:52:42 +08:00
										 |  |  | 	"k8s.io/apimachinery/pkg/api/meta" | 
					
						
							| 
									
										
										
										
											2020-02-21 03:56:03 +08:00
										 |  |  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 	"k8s.io/cli-runtime/pkg/resource" | 
					
						
							| 
									
										
										
										
											2020-02-21 03:56:03 +08:00
										 |  |  | 	"sigs.k8s.io/yaml" | 
					
						
							| 
									
										
										
										
											2019-01-09 05:37:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-26 04:20:44 +08:00
										 |  |  | 	chart "helm.sh/helm/v4/pkg/chart/v2" | 
					
						
							|  |  |  | 	chartutil "helm.sh/helm/v4/pkg/chart/v2/util" | 
					
						
							| 
									
										
										
										
											2024-12-27 05:33:51 +08:00
										 |  |  | 	"helm.sh/helm/v4/pkg/cli" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/downloader" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/getter" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/kube" | 
					
						
							|  |  |  | 	kubefake "helm.sh/helm/v4/pkg/kube/fake" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/postrender" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/registry" | 
					
						
							| 
									
										
										
										
											2025-02-25 03:58:51 +08:00
										 |  |  | 	releaseutil "helm.sh/helm/v4/pkg/release/util" | 
					
						
							| 
									
										
										
										
											2025-02-26 22:04:32 +08:00
										 |  |  | 	release "helm.sh/helm/v4/pkg/release/v1" | 
					
						
							| 
									
										
										
										
											2024-12-27 05:33:51 +08:00
										 |  |  | 	"helm.sh/helm/v4/pkg/repo" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/storage" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/storage/driver" | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-05 11:51:39 +08:00
										 |  |  | // notesFileSuffix that we want to treat special. It goes through the templating engine
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | // but it's not a yaml file (resource) hence can't have hooks, etc. And the user actually
 | 
					
						
							|  |  |  | // wants to see this file after rendering in the status command. However, it must be a suffix
 | 
					
						
							|  |  |  | // since there can be filepath in front of it.
 | 
					
						
							|  |  |  | const notesFileSuffix = "NOTES.txt" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 16:46:42 +08:00
										 |  |  | const defaultDirectoryPermission = 0755 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | // Install performs an installation operation.
 | 
					
						
							|  |  |  | type Install struct { | 
					
						
							|  |  |  | 	cfg *Configuration | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	ChartPathOptions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-13 01:56:10 +08:00
										 |  |  | 	ClientOnly      bool | 
					
						
							|  |  |  | 	Force           bool | 
					
						
							|  |  |  | 	CreateNamespace bool | 
					
						
							|  |  |  | 	DryRun          bool | 
					
						
							|  |  |  | 	DryRunOption    string | 
					
						
							|  |  |  | 	// HideSecret can be set to true when DryRun is enabled in order to hide
 | 
					
						
							|  |  |  | 	// Kubernetes Secrets in the output. It cannot be used outside of DryRun.
 | 
					
						
							|  |  |  | 	HideSecret               bool | 
					
						
							| 
									
										
										
										
											2019-10-30 02:17:54 +08:00
										 |  |  | 	DisableHooks             bool | 
					
						
							|  |  |  | 	Replace                  bool | 
					
						
							|  |  |  | 	Wait                     bool | 
					
						
							| 
									
										
										
										
											2020-11-03 19:48:29 +08:00
										 |  |  | 	WaitForJobs              bool | 
					
						
							| 
									
										
										
										
											2019-10-30 02:17:54 +08:00
										 |  |  | 	Devel                    bool | 
					
						
							|  |  |  | 	DependencyUpdate         bool | 
					
						
							|  |  |  | 	Timeout                  time.Duration | 
					
						
							|  |  |  | 	Namespace                string | 
					
						
							|  |  |  | 	ReleaseName              string | 
					
						
							|  |  |  | 	GenerateName             bool | 
					
						
							|  |  |  | 	NameTemplate             string | 
					
						
							|  |  |  | 	Description              string | 
					
						
							|  |  |  | 	OutputDir                string | 
					
						
							|  |  |  | 	Atomic                   bool | 
					
						
							|  |  |  | 	SkipCRDs                 bool | 
					
						
							|  |  |  | 	SubNotes                 bool | 
					
						
							| 
									
										
										
										
											2022-12-05 13:44:33 +08:00
										 |  |  | 	HideNotes                bool | 
					
						
							| 
									
										
										
										
											2024-01-23 23:32:03 +08:00
										 |  |  | 	SkipSchemaValidation     bool | 
					
						
							| 
									
										
										
										
											2019-10-30 02:17:54 +08:00
										 |  |  | 	DisableOpenAPIValidation bool | 
					
						
							| 
									
										
										
										
											2020-02-05 05:16:51 +08:00
										 |  |  | 	IncludeCRDs              bool | 
					
						
							| 
									
										
										
										
											2022-01-07 23:24:09 +08:00
										 |  |  | 	Labels                   map[string]string | 
					
						
							| 
									
										
										
										
											2020-11-20 17:32:29 +08:00
										 |  |  | 	// KubeVersion allows specifying a custom kubernetes version to use and
 | 
					
						
							| 
									
										
										
										
											2019-10-08 03:23:42 +08:00
										 |  |  | 	// APIVersions allows a manual set of supported API Versions to be passed
 | 
					
						
							|  |  |  | 	// (for things like templating). These are ignored if ClientOnly is false
 | 
					
						
							| 
									
										
										
										
											2020-11-20 17:32:29 +08:00
										 |  |  | 	KubeVersion *chartutil.KubeVersion | 
					
						
							| 
									
										
										
										
											2019-10-08 03:23:42 +08:00
										 |  |  | 	APIVersions chartutil.VersionSet | 
					
						
							| 
									
										
										
										
											2019-12-18 20:04:08 +08:00
										 |  |  | 	// Used by helm template to render charts with .Release.IsUpgrade. Ignored if Dry-Run is false
 | 
					
						
							| 
									
										
										
										
											2019-11-22 23:27:08 +08:00
										 |  |  | 	IsUpgrade bool | 
					
						
							| 
									
										
										
										
											2023-02-02 00:35:19 +08:00
										 |  |  | 	// Enable DNS lookups when rendering templates
 | 
					
						
							|  |  |  | 	EnableDNS bool | 
					
						
							| 
									
										
										
										
											2020-02-05 00:27:38 +08:00
										 |  |  | 	// Used by helm template to add the release as part of OutputDir path
 | 
					
						
							|  |  |  | 	// OutputDir/<ReleaseName>
 | 
					
						
							|  |  |  | 	UseReleaseName bool | 
					
						
							| 
									
										
										
										
											2024-03-13 21:09:23 +08:00
										 |  |  | 	// TakeOwnership will ignore the check for helm annotations and take ownership of the resources.
 | 
					
						
							|  |  |  | 	TakeOwnership bool | 
					
						
							|  |  |  | 	PostRenderer  postrender.PostRenderer | 
					
						
							| 
									
										
										
										
											2021-07-04 19:04:35 +08:00
										 |  |  | 	// Lock to control raceconditions when the process receives a SIGTERM
 | 
					
						
							|  |  |  | 	Lock sync.Mutex | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 06:26:09 +08:00
										 |  |  | // ChartPathOptions captures common options used for controlling chart paths
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | type ChartPathOptions struct { | 
					
						
							| 
									
										
										
										
											2020-05-01 19:21:44 +08:00
										 |  |  | 	CaFile                string // --ca-file
 | 
					
						
							|  |  |  | 	CertFile              string // --cert-file
 | 
					
						
							|  |  |  | 	KeyFile               string // --key-file
 | 
					
						
							|  |  |  | 	InsecureSkipTLSverify bool   // --insecure-skip-verify
 | 
					
						
							| 
									
										
										
										
											2023-06-07 14:24:02 +08:00
										 |  |  | 	PlainHTTP             bool   // --plain-http
 | 
					
						
							| 
									
										
										
										
											2020-05-01 19:21:44 +08:00
										 |  |  | 	Keyring               string // --keyring
 | 
					
						
							|  |  |  | 	Password              string // --password
 | 
					
						
							| 
									
										
										
										
											2021-06-12 02:36:55 +08:00
										 |  |  | 	PassCredentialsAll    bool   // --pass-credentials
 | 
					
						
							| 
									
										
										
										
											2020-05-01 19:21:44 +08:00
										 |  |  | 	RepoURL               string // --repo
 | 
					
						
							|  |  |  | 	Username              string // --username
 | 
					
						
							|  |  |  | 	Verify                bool   // --verify
 | 
					
						
							|  |  |  | 	Version               string // --version
 | 
					
						
							| 
									
										
										
										
											2022-01-13 10:26:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// registryClient provides a registry client but is not added with
 | 
					
						
							|  |  |  | 	// options from a flag
 | 
					
						
							|  |  |  | 	registryClient *registry.Client | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewInstall creates a new Install object with the given configuration.
 | 
					
						
							|  |  |  | func NewInstall(cfg *Configuration) *Install { | 
					
						
							| 
									
										
										
										
											2022-01-13 10:26:41 +08:00
										 |  |  | 	in := &Install{ | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 		cfg: cfg, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-01-13 10:26:41 +08:00
										 |  |  | 	in.ChartPathOptions.registryClient = cfg.RegistryClient | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return in | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-20 05:52:20 +08:00
										 |  |  | // SetRegistryClient sets the registry client for the install action
 | 
					
						
							|  |  |  | func (i *Install) SetRegistryClient(registryClient *registry.Client) { | 
					
						
							|  |  |  | 	i.ChartPathOptions.registryClient = registryClient | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 14:52:16 +08:00
										 |  |  | // GetRegistryClient get the registry client.
 | 
					
						
							|  |  |  | func (i *Install) GetRegistryClient() *registry.Client { | 
					
						
							|  |  |  | 	return i.ChartPathOptions.registryClient | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-21 05:31:26 +08:00
										 |  |  | func (i *Install) installCRDs(crds []chart.CRD) error { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 	// We do these one file at a time in the order they were read.
 | 
					
						
							|  |  |  | 	totalItems := []*resource.Info{} | 
					
						
							|  |  |  | 	for _, obj := range crds { | 
					
						
							|  |  |  | 		// Read in the resources
 | 
					
						
							| 
									
										
										
										
											2020-01-21 05:31:26 +08:00
										 |  |  | 		res, err := i.cfg.KubeClient.Build(bytes.NewBuffer(obj.File.Data), false) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return errors.Wrapf(err, "failed to install CRD %s", obj.Name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Send them to Kube
 | 
					
						
							|  |  |  | 		if _, err := i.cfg.KubeClient.Create(res); err != nil { | 
					
						
							|  |  |  | 			// If the error is CRD already exists, continue.
 | 
					
						
							|  |  |  | 			if apierrors.IsAlreadyExists(err) { | 
					
						
							|  |  |  | 				crdName := res[0].Name | 
					
						
							|  |  |  | 				i.cfg.Log("CRD %s is already present. Skipping.", crdName) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-11-13 10:41:01 +08:00
										 |  |  | 			return errors.Wrapf(err, "failed to install CRD %s", obj.Name) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		totalItems = append(totalItems, res...) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-16 06:21:55 +08:00
										 |  |  | 	if len(totalItems) > 0 { | 
					
						
							|  |  |  | 		// Give time for the CRD to be recognized.
 | 
					
						
							| 
									
										
										
										
											2020-11-05 17:13:15 +08:00
										 |  |  | 		if err := i.cfg.KubeClient.Wait(totalItems, 60*time.Second); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-16 06:21:55 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 01:52:42 +08:00
										 |  |  | 		// If we have already gathered the capabilities, we need to invalidate
 | 
					
						
							|  |  |  | 		// the cache so that the new CRDs are recognized. This should only be
 | 
					
						
							|  |  |  | 		// the case when an action configuration is reused for multiple actions,
 | 
					
						
							|  |  |  | 		// as otherwise it is later loaded by ourselves when getCapabilities
 | 
					
						
							|  |  |  | 		// is called later on in the installation process.
 | 
					
						
							|  |  |  | 		if i.cfg.Capabilities != nil { | 
					
						
							|  |  |  | 			discoveryClient, err := i.cfg.RESTClientGetter.ToDiscoveryClient() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			i.cfg.Log("Clearing discovery cache") | 
					
						
							|  |  |  | 			discoveryClient.Invalidate() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_, _ = discoveryClient.ServerGroups() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Invalidate the REST mapper, since it will not have the new CRDs
 | 
					
						
							|  |  |  | 		// present.
 | 
					
						
							|  |  |  | 		restMapper, err := i.cfg.RESTClientGetter.ToRESTMapper() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if resettable, ok := restMapper.(meta.ResettableRESTMapper); ok { | 
					
						
							|  |  |  | 			i.cfg.Log("Clearing REST mapper cache") | 
					
						
							|  |  |  | 			resettable.Reset() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | // Run executes the installation
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // If DryRun is set to true, this will prepare the release, but not install it
 | 
					
						
							| 
									
										
										
										
											2021-07-26 08:04:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 23:04:36 +08:00
										 |  |  | func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) { | 
					
						
							| 
									
										
										
										
											2021-07-26 08:04:58 +08:00
										 |  |  | 	ctx := context.Background() | 
					
						
							|  |  |  | 	return i.RunWithContext(ctx, chrt, vals) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Run executes the installation with Context
 | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // When the task is cancelled through ctx, the function returns and the install
 | 
					
						
							|  |  |  | // proceeds in the background.
 | 
					
						
							| 
									
										
										
										
											2021-07-26 08:04:58 +08:00
										 |  |  | func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) { | 
					
						
							| 
									
										
										
										
											2019-09-13 20:14:25 +08:00
										 |  |  | 	// Check reachability of cluster unless in client-only mode (e.g. `helm template` without `--validate`)
 | 
					
						
							|  |  |  | 	if !i.ClientOnly { | 
					
						
							|  |  |  | 		if err := i.cfg.KubeClient.IsReachable(); err != nil { | 
					
						
							| 
									
										
										
										
											2024-12-17 13:07:56 +08:00
										 |  |  | 			i.cfg.Log(fmt.Sprintf("ERROR: Cluster reachability check failed: %v", err)) | 
					
						
							|  |  |  | 			return nil, errors.Wrap(err, "cluster reachability check failed") | 
					
						
							| 
									
										
										
										
											2019-09-13 20:14:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-26 05:46:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-13 01:56:10 +08:00
										 |  |  | 	// HideSecret must be used with dry run. Otherwise, return an error.
 | 
					
						
							|  |  |  | 	if !i.isDryRun() && i.HideSecret { | 
					
						
							| 
									
										
										
										
											2024-12-17 13:07:56 +08:00
										 |  |  | 		i.cfg.Log("ERROR: Hiding Kubernetes secrets requires a dry-run mode") | 
					
						
							| 
									
										
										
										
											2024-12-17 13:27:20 +08:00
										 |  |  | 		return nil, errors.New("Hiding Kubernetes secrets requires a dry-run mode") | 
					
						
							| 
									
										
										
										
											2024-03-13 01:56:10 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	if err := i.availableName(); err != nil { | 
					
						
							| 
									
										
										
										
											2024-12-17 13:07:56 +08:00
										 |  |  | 		i.cfg.Log(fmt.Sprintf("ERROR: Release name check failed: %v", err)) | 
					
						
							|  |  |  | 		return nil, errors.Wrap(err, "release name check failed") | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 07:36:06 +08:00
										 |  |  | 	if err := chartutil.ProcessDependencies(chrt, vals); err != nil { | 
					
						
							| 
									
										
										
										
											2024-12-17 13:07:56 +08:00
										 |  |  | 		i.cfg.Log(fmt.Sprintf("ERROR: Processing chart dependencies failed: %v", err)) | 
					
						
							|  |  |  | 		return nil, errors.Wrap(err, "chart dependencies processing failed") | 
					
						
							| 
									
										
										
										
											2021-09-01 13:57:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-24 03:18:59 +08:00
										 |  |  | 	var interactWithRemote bool | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | 	if !i.isDryRun() || i.DryRunOption == "server" || i.DryRunOption == "none" || i.DryRunOption == "false" { | 
					
						
							| 
									
										
										
										
											2023-01-24 03:18:59 +08:00
										 |  |  | 		interactWithRemote = true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 	// Pre-install anything in the crd/ directory. We do this before Helm
 | 
					
						
							|  |  |  | 	// contacts the upstream server and builds the capabilities object.
 | 
					
						
							| 
									
										
										
										
											2020-01-28 06:06:06 +08:00
										 |  |  | 	if crds := chrt.CRDObjects(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 		// On dry run, bail here
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | 		if i.isDryRun() { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:32:24 +08:00
										 |  |  | 			i.cfg.Log("WARNING: This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.") | 
					
						
							|  |  |  | 		} else if err := i.installCRDs(crds); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-20 03:27:14 +08:00
										 |  |  | 	if i.ClientOnly { | 
					
						
							|  |  |  | 		// Add mock objects in here so it doesn't use Kube API server
 | 
					
						
							|  |  |  | 		// NOTE(bacongobbler): used for `helm template`
 | 
					
						
							| 
									
										
										
										
											2020-11-27 15:28:26 +08:00
										 |  |  | 		i.cfg.Capabilities = chartutil.DefaultCapabilities.Copy() | 
					
						
							| 
									
										
										
										
											2020-11-20 17:32:29 +08:00
										 |  |  | 		if i.KubeVersion != nil { | 
					
						
							|  |  |  | 			i.cfg.Capabilities.KubeVersion = *i.KubeVersion | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-08 03:23:42 +08:00
										 |  |  | 		i.cfg.Capabilities.APIVersions = append(i.cfg.Capabilities.APIVersions, i.APIVersions...) | 
					
						
							| 
									
										
										
										
											2023-03-22 21:31:16 +08:00
										 |  |  | 		i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: io.Discard} | 
					
						
							| 
									
										
										
										
											2020-01-30 11:56:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		mem := driver.NewMemory() | 
					
						
							|  |  |  | 		mem.SetNamespace(i.Namespace) | 
					
						
							|  |  |  | 		i.cfg.Releases = storage.Init(mem) | 
					
						
							| 
									
										
										
										
											2019-10-08 03:23:42 +08:00
										 |  |  | 	} else if !i.ClientOnly && len(i.APIVersions) > 0 { | 
					
						
							|  |  |  | 		i.cfg.Log("API Version list given outside of client only mode, this list will be ignored") | 
					
						
							| 
									
										
										
										
											2019-07-20 03:27:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 03:36:34 +08:00
										 |  |  | 	// Make sure if Atomic is set, that wait is set as well. This makes it so
 | 
					
						
							|  |  |  | 	// the user doesn't have to specify both
 | 
					
						
							|  |  |  | 	i.Wait = i.Wait || i.Atomic | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-08 03:02:07 +08:00
										 |  |  | 	caps, err := i.cfg.getCapabilities() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-26 13:47:14 +08:00
										 |  |  | 	// special case for helm template --is-upgrade
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | 	isUpgrade := i.IsUpgrade && i.isDryRun() | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	options := chartutil.ReleaseOptions{ | 
					
						
							|  |  |  | 		Name:      i.ReleaseName, | 
					
						
							| 
									
										
										
										
											2019-05-16 05:08:51 +08:00
										 |  |  | 		Namespace: i.Namespace, | 
					
						
							| 
									
										
										
										
											2019-10-18 02:04:45 +08:00
										 |  |  | 		Revision:  1, | 
					
						
							| 
									
										
										
										
											2019-11-22 23:27:08 +08:00
										 |  |  | 		IsInstall: !isUpgrade, | 
					
						
							|  |  |  | 		IsUpgrade: isUpgrade, | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-01-23 23:32:03 +08:00
										 |  |  | 	valuesToRender, err := chartutil.ToRenderValuesWithSchemaValidation(chrt, vals, options, caps, i.SkipSchemaValidation) | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 22:41:14 +08:00
										 |  |  | 	if driver.ContainsSystemLabels(i.Labels) { | 
					
						
							| 
									
										
										
										
											2024-09-05 11:51:39 +08:00
										 |  |  | 		return nil, fmt.Errorf("user supplied labels contains system reserved label name. System labels: %+v", driver.GetSystemLabels()) | 
					
						
							| 
									
										
										
										
											2023-07-25 22:41:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 23:24:09 +08:00
										 |  |  | 	rel := i.createRelease(chrt, vals, i.Labels) | 
					
						
							| 
									
										
										
										
											2019-08-17 06:26:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	var manifestDoc *bytes.Buffer | 
					
						
							| 
									
										
										
										
											2024-03-13 01:56:10 +08:00
										 |  |  | 	rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.ReleaseName, i.OutputDir, i.SubNotes, i.UseReleaseName, i.IncludeCRDs, i.PostRenderer, interactWithRemote, i.EnableDNS, i.HideSecret) | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	// Even for errors, attach this if available
 | 
					
						
							|  |  |  | 	if manifestDoc != nil { | 
					
						
							|  |  |  | 		rel.Manifest = manifestDoc.String() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Check error from render
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		rel.SetStatus(release.StatusFailed, fmt.Sprintf("failed to render resource: %s", err.Error())) | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 		// Return a release with partial data so that the client can show debugging information.
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 		return rel, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Mark this release as in-progress
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	rel.SetStatus(release.StatusPendingInstall, "Initial install underway") | 
					
						
							| 
									
										
										
										
											2019-07-25 04:24:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 10:41:30 +08:00
										 |  |  | 	var toBeAdopted kube.ResourceList | 
					
						
							| 
									
										
										
										
											2019-10-30 02:17:54 +08:00
										 |  |  | 	resources, err := i.cfg.KubeClient.Build(bytes.NewBufferString(rel.Manifest), !i.DisableOpenAPIValidation) | 
					
						
							| 
									
										
										
										
											2019-07-25 04:24:32 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, errors.Wrap(err, "unable to build kubernetes objects from release manifest") | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 10:22:15 +08:00
										 |  |  | 	// It is safe to use "force" here because these are resources currently rendered by the chart.
 | 
					
						
							|  |  |  | 	err = resources.Visit(setMetadataVisitor(rel.Name, rel.Namespace, true)) | 
					
						
							| 
									
										
										
										
											2020-02-21 09:53:27 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-01 06:05:41 +08:00
										 |  |  | 	// Install requires an extra validation step of checking that resources
 | 
					
						
							|  |  |  | 	// don't already exist before we actually create resources. If we continue
 | 
					
						
							|  |  |  | 	// forward and create the release object with resources that already exist,
 | 
					
						
							|  |  |  | 	// we'll end up in a state where we will delete those resources upon
 | 
					
						
							|  |  |  | 	// deleting the release because the manifest will be pointing at that
 | 
					
						
							|  |  |  | 	// resource
 | 
					
						
							| 
									
										
										
										
											2020-04-16 06:21:55 +08:00
										 |  |  | 	if !i.ClientOnly && !isUpgrade && len(resources) > 0 { | 
					
						
							| 
									
										
										
										
											2024-03-13 21:09:23 +08:00
										 |  |  | 		if i.TakeOwnership { | 
					
						
							|  |  |  | 			toBeAdopted, err = requireAdoption(resources) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			toBeAdopted, err = existingResourceConflict(resources, rel.Name, rel.Namespace) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-21 08:42:47 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2021-11-24 18:15:15 +08:00
										 |  |  | 			return nil, errors.Wrap(err, "Unable to continue with install") | 
					
						
							| 
									
										
										
										
											2019-10-02 03:38:57 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Bail out here if it is a dry run
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | 	if i.isDryRun() { | 
					
						
							| 
									
										
										
										
											2019-10-02 03:38:57 +08:00
										 |  |  | 		rel.Info.Description = "Dry run complete" | 
					
						
							|  |  |  | 		return rel, nil | 
					
						
							| 
									
										
										
										
											2019-10-01 06:05:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 03:56:03 +08:00
										 |  |  | 	if i.CreateNamespace { | 
					
						
							|  |  |  | 		ns := &v1.Namespace{ | 
					
						
							|  |  |  | 			TypeMeta: metav1.TypeMeta{ | 
					
						
							|  |  |  | 				APIVersion: "v1", | 
					
						
							|  |  |  | 				Kind:       "Namespace", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ObjectMeta: metav1.ObjectMeta{ | 
					
						
							|  |  |  | 				Name: i.Namespace, | 
					
						
							|  |  |  | 				Labels: map[string]string{ | 
					
						
							|  |  |  | 					"name": i.Namespace, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		buf, err := yaml.Marshal(ns) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		resourceList, err := i.cfg.KubeClient.Build(bytes.NewBuffer(buf), true) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if _, err := i.cfg.KubeClient.Create(resourceList); err != nil && !apierrors.IsAlreadyExists(err) { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-05 11:51:39 +08:00
										 |  |  | 	// If Replace is true, we need to supersede the last release.
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	if i.Replace { | 
					
						
							|  |  |  | 		if err := i.replaceRelease(rel); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Store the release in history before continuing (new in Helm 3). We always know
 | 
					
						
							|  |  |  | 	// that this is a create operation.
 | 
					
						
							|  |  |  | 	if err := i.cfg.Releases.Create(rel); err != nil { | 
					
						
							|  |  |  | 		// We could try to recover gracefully here, but since nothing has been installed
 | 
					
						
							|  |  |  | 		// yet, this is probably safer than trying to continue when we know storage is
 | 
					
						
							|  |  |  | 		// not working.
 | 
					
						
							|  |  |  | 		return rel, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rel, err = i.performInstallCtx(ctx, rel, toBeAdopted, resources) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		rel, err = i.failRelease(rel, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return rel, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (i *Install) performInstallCtx(ctx context.Context, rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) (*release.Release, error) { | 
					
						
							|  |  |  | 	type Msg struct { | 
					
						
							|  |  |  | 		r *release.Release | 
					
						
							|  |  |  | 		e error | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	resultChan := make(chan Msg, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		rel, err := i.performInstall(rel, toBeAdopted, resources) | 
					
						
							|  |  |  | 		resultChan <- Msg{rel, err} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2023-04-11 04:45:41 +08:00
										 |  |  | 	select { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 	case <-ctx.Done(): | 
					
						
							|  |  |  | 		err := ctx.Err() | 
					
						
							|  |  |  | 		return rel, err | 
					
						
							|  |  |  | 	case msg := <-resultChan: | 
					
						
							|  |  |  | 		return msg.r, msg.e | 
					
						
							| 
									
										
										
										
											2023-04-11 04:45:41 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-08 19:29:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | // isDryRun returns true if Upgrade is set to run as a DryRun
 | 
					
						
							|  |  |  | func (i *Install) isDryRun() bool { | 
					
						
							|  |  |  | 	if i.DryRun || i.DryRunOption == "client" || i.DryRunOption == "server" || i.DryRunOption == "true" { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							| 
									
										
										
										
											2021-01-08 19:29:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | func (i *Install) performInstall(rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) (*release.Release, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	// pre-install hooks
 | 
					
						
							|  |  |  | 	if !i.DisableHooks { | 
					
						
							| 
									
										
										
										
											2019-07-26 02:45:03 +08:00
										 |  |  | 		if err := i.cfg.execHook(rel, release.HookPreInstall, i.Timeout); err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 			return rel, fmt.Errorf("failed pre-install: %s", err) | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// At this point, we can do the install. Note that before we were detecting whether to
 | 
					
						
							| 
									
										
										
										
											2024-11-07 19:30:34 +08:00
										 |  |  | 	// do an update, but it's not clear whether we WANT to do an update if the reuse is set
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	// to true, since that is basically an upgrade operation.
 | 
					
						
							| 
									
										
										
										
											2020-04-16 06:21:55 +08:00
										 |  |  | 	if len(toBeAdopted) == 0 && len(resources) > 0 { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 		_, err = i.cfg.KubeClient.Create(resources) | 
					
						
							| 
									
										
										
										
											2020-04-16 06:21:55 +08:00
										 |  |  | 	} else if len(resources) > 0 { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 		_, err = i.cfg.KubeClient.Update(toBeAdopted, resources, i.Force) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return rel, err | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-25 08:18:42 +08:00
										 |  |  | 	if i.Wait { | 
					
						
							| 
									
										
										
										
											2020-11-05 17:13:15 +08:00
										 |  |  | 		if i.WaitForJobs { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 			err = i.cfg.KubeClient.WaitWithJobs(resources, i.Timeout) | 
					
						
							| 
									
										
										
										
											2020-11-05 17:13:15 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 			err = i.cfg.KubeClient.Wait(resources, i.Timeout) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return rel, err | 
					
						
							| 
									
										
										
										
											2019-04-25 08:18:42 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	if !i.DisableHooks { | 
					
						
							| 
									
										
										
										
											2019-07-26 02:45:03 +08:00
										 |  |  | 		if err := i.cfg.execHook(rel, release.HookPostInstall, i.Timeout); err != nil { | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 			return rel, fmt.Errorf("failed post-install: %s", err) | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 00:48:31 +08:00
										 |  |  | 	if len(i.Description) > 0 { | 
					
						
							|  |  |  | 		rel.SetStatus(release.StatusDeployed, i.Description) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		rel.SetStatus(release.StatusDeployed, "Install complete") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// This is a tricky case. The release has been created, but the result
 | 
					
						
							|  |  |  | 	// cannot be recorded. The truest thing to tell the user is that the
 | 
					
						
							|  |  |  | 	// release was created. However, the user will not be able to do anything
 | 
					
						
							|  |  |  | 	// further with this release.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// One possible strategy would be to do a timed retry to see if we can get
 | 
					
						
							|  |  |  | 	// this stored in the future.
 | 
					
						
							| 
									
										
										
										
											2019-11-13 05:12:45 +08:00
										 |  |  | 	if err := i.recordRelease(rel); err != nil { | 
					
						
							|  |  |  | 		i.cfg.Log("failed to record the release: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 	return rel, nil | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-07-17 03:13:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 03:36:34 +08:00
										 |  |  | func (i *Install) failRelease(rel *release.Release, err error) (*release.Release, error) { | 
					
						
							|  |  |  | 	rel.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", i.ReleaseName, err.Error())) | 
					
						
							|  |  |  | 	if i.Atomic { | 
					
						
							| 
									
										
										
										
											2019-07-12 02:28:22 +08:00
										 |  |  | 		i.cfg.Log("Install failed and atomic is set, uninstalling release") | 
					
						
							| 
									
										
										
										
											2019-07-09 03:36:34 +08:00
										 |  |  | 		uninstall := NewUninstall(i.cfg) | 
					
						
							|  |  |  | 		uninstall.DisableHooks = i.DisableHooks | 
					
						
							|  |  |  | 		uninstall.KeepHistory = false | 
					
						
							|  |  |  | 		uninstall.Timeout = i.Timeout | 
					
						
							|  |  |  | 		if _, uninstallErr := uninstall.Run(i.ReleaseName); uninstallErr != nil { | 
					
						
							| 
									
										
										
										
											2019-07-12 02:28:22 +08:00
										 |  |  | 			return rel, errors.Wrapf(uninstallErr, "an error occurred while uninstalling the release. original install error: %s", err) | 
					
						
							| 
									
										
										
										
											2019-07-09 03:36:34 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-12 02:28:22 +08:00
										 |  |  | 		return rel, errors.Wrapf(err, "release %s failed, and has been uninstalled due to atomic being set", i.ReleaseName) | 
					
						
							| 
									
										
										
										
											2019-07-09 03:36:34 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	i.recordRelease(rel) // Ignore the error, since we have another error to deal with.
 | 
					
						
							|  |  |  | 	return rel, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | // availableName tests whether a name is available
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Roughly, this will return an error if name is
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2023-02-02 00:35:19 +08:00
										 |  |  | //   - empty
 | 
					
						
							|  |  |  | //   - too long
 | 
					
						
							|  |  |  | //   - already in use, and not deleted
 | 
					
						
							|  |  |  | //   - used by a deleted release, and i.Replace is false
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | func (i *Install) availableName() error { | 
					
						
							|  |  |  | 	start := i.ReleaseName | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 12:09:28 +08:00
										 |  |  | 	if err := chartutil.ValidateReleaseName(start); err != nil { | 
					
						
							|  |  |  | 		return errors.Wrapf(err, "release name %q", start) | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-01-16 16:29:19 +08:00
										 |  |  | 	// On dry run, bail here
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:26:46 +08:00
										 |  |  | 	if i.isDryRun() { | 
					
						
							| 
									
										
										
										
											2019-07-31 03:54:23 +08:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	h, err := i.cfg.Releases.History(start) | 
					
						
							|  |  |  | 	if err != nil || len(h) < 1 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	releaseutil.Reverse(h, releaseutil.SortByRevision) | 
					
						
							|  |  |  | 	rel := h[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if st := rel.Info.Status; i.Replace && (st == release.StatusUninstalled || st == release.StatusFailed) { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-11-07 19:30:34 +08:00
										 |  |  | 	return errors.New("cannot reuse a name that is still in use") | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // createRelease creates a new release object
 | 
					
						
							| 
									
										
										
										
											2022-01-07 23:24:09 +08:00
										 |  |  | func (i *Install) createRelease(chrt *chart.Chart, rawVals map[string]interface{}, labels map[string]string) *release.Release { | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	ts := i.cfg.Now() | 
					
						
							|  |  |  | 	return &release.Release{ | 
					
						
							|  |  |  | 		Name:      i.ReleaseName, | 
					
						
							|  |  |  | 		Namespace: i.Namespace, | 
					
						
							|  |  |  | 		Chart:     chrt, | 
					
						
							|  |  |  | 		Config:    rawVals, | 
					
						
							|  |  |  | 		Info: &release.Info{ | 
					
						
							|  |  |  | 			FirstDeployed: ts, | 
					
						
							|  |  |  | 			LastDeployed:  ts, | 
					
						
							|  |  |  | 			Status:        release.StatusUnknown, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Version: 1, | 
					
						
							| 
									
										
										
										
											2022-01-07 23:24:09 +08:00
										 |  |  | 		Labels:  labels, | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // recordRelease with an update operation in case reuse has been set.
 | 
					
						
							|  |  |  | func (i *Install) recordRelease(r *release.Release) error { | 
					
						
							|  |  |  | 	// This is a legacy function which has been reduced to a oneliner. Could probably
 | 
					
						
							|  |  |  | 	// refactor it out.
 | 
					
						
							|  |  |  | 	return i.cfg.Releases.Update(r) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // replaceRelease replaces an older release with this one
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2024-11-07 19:30:34 +08:00
										 |  |  | // This allows us to reuse names by superseding an existing release with a new one
 | 
					
						
							| 
									
										
										
										
											2019-01-08 08:45:14 +08:00
										 |  |  | func (i *Install) replaceRelease(rel *release.Release) error { | 
					
						
							|  |  |  | 	hist, err := i.cfg.Releases.History(rel.Name) | 
					
						
							|  |  |  | 	if err != nil || len(hist) == 0 { | 
					
						
							|  |  |  | 		// No releases exist for this name, so we can return early
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	releaseutil.Reverse(hist, releaseutil.SortByRevision) | 
					
						
							|  |  |  | 	last := hist[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Update version to the next available
 | 
					
						
							|  |  |  | 	rel.Version = last.Version + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Do not change the status of a failed release.
 | 
					
						
							|  |  |  | 	if last.Info.Status == release.StatusFailed { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// For any other status, mark it as superseded and store the old record
 | 
					
						
							|  |  |  | 	last.SetStatus(release.StatusSuperseded, "superseded by new release") | 
					
						
							|  |  |  | 	return i.recordRelease(last) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 01:40:37 +08:00
										 |  |  | // write the <data> to <output-dir>/<name>. <appendData> controls if the file is created or content will be appended
 | 
					
						
							|  |  |  | func writeToFile(outputDir string, name string, data string, appendData bool) error { | 
					
						
							| 
									
										
										
										
											2019-05-20 16:46:42 +08:00
										 |  |  | 	outfileName := strings.Join([]string{outputDir, name}, string(filepath.Separator)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := ensureDirectoryForFile(outfileName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 01:40:37 +08:00
										 |  |  | 	f, err := createOrOpenFile(outfileName, appendData) | 
					
						
							| 
									
										
										
										
											2019-05-20 16:46:42 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer f.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-12 21:31:34 +08:00
										 |  |  | 	_, err = f.WriteString(fmt.Sprintf("---\n# Source: %s\n%s\n", name, data)) | 
					
						
							| 
									
										
										
										
											2019-05-20 16:46:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Printf("wrote %s\n", outfileName) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 01:40:37 +08:00
										 |  |  | func createOrOpenFile(filename string, appendData bool) (*os.File, error) { | 
					
						
							|  |  |  | 	if appendData { | 
					
						
							| 
									
										
										
										
											2019-06-12 21:31:34 +08:00
										 |  |  | 		return os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0600) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return os.Create(filename) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-13 05:33:46 +08:00
										 |  |  | // check if the directory exists to create file. creates if doesn't exist
 | 
					
						
							| 
									
										
										
										
											2019-05-20 16:46:42 +08:00
										 |  |  | func ensureDirectoryForFile(file string) error { | 
					
						
							|  |  |  | 	baseDir := path.Dir(file) | 
					
						
							|  |  |  | 	_, err := os.Stat(baseDir) | 
					
						
							|  |  |  | 	if err != nil && !os.IsNotExist(err) { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return os.MkdirAll(baseDir, defaultDirectoryPermission) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | // NameAndChart returns the name and chart that should be used.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This will read the flags and handle name generation if necessary.
 | 
					
						
							|  |  |  | func (i *Install) NameAndChart(args []string) (string, string, error) { | 
					
						
							|  |  |  | 	flagsNotSet := func() error { | 
					
						
							|  |  |  | 		if i.GenerateName { | 
					
						
							|  |  |  | 			return errors.New("cannot set --generate-name and also specify a name") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if i.NameTemplate != "" { | 
					
						
							|  |  |  | 			return errors.New("cannot set --name-template and also specify a name") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 01:14:06 +08:00
										 |  |  | 	if len(args) > 2 { | 
					
						
							|  |  |  | 		return args[0], args[1], errors.Errorf("expected at most two arguments, unexpected arguments: %v", strings.Join(args[2:], ", ")) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	if len(args) == 2 { | 
					
						
							|  |  |  | 		return args[0], args[1], flagsNotSet() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if i.NameTemplate != "" { | 
					
						
							|  |  |  | 		name, err := TemplateName(i.NameTemplate) | 
					
						
							|  |  |  | 		return name, args[0], err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if i.ReleaseName != "" { | 
					
						
							|  |  |  | 		return i.ReleaseName, args[0], nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !i.GenerateName { | 
					
						
							|  |  |  | 		return "", args[0], errors.New("must either provide a name or specify --generate-name") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	base := filepath.Base(args[0]) | 
					
						
							|  |  |  | 	if base == "." || base == "" { | 
					
						
							|  |  |  | 		base = "chart" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-31 04:09:43 +08:00
										 |  |  | 	// if present, strip out the file extension from the name
 | 
					
						
							|  |  |  | 	if idx := strings.Index(base, "."); idx != -1 { | 
					
						
							|  |  |  | 		base = base[0:idx] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s-%d", base, time.Now().Unix()), args[0], nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 06:26:09 +08:00
										 |  |  | // TemplateName renders a name template, returning the name or an error.
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | func TemplateName(nameTemplate string) (string, error) { | 
					
						
							|  |  |  | 	if nameTemplate == "" { | 
					
						
							|  |  |  | 		return "", nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t, err := template.New("name-template").Funcs(sprig.TxtFuncMap()).Parse(nameTemplate) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var b bytes.Buffer | 
					
						
							|  |  |  | 	if err := t.Execute(&b, nil); err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return b.String(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 06:26:09 +08:00
										 |  |  | // CheckDependencies checks the dependencies for a chart.
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | func CheckDependencies(ch *chart.Chart, reqs []*chart.Dependency) error { | 
					
						
							|  |  |  | 	var missing []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OUTER: | 
					
						
							|  |  |  | 	for _, r := range reqs { | 
					
						
							|  |  |  | 		for _, d := range ch.Dependencies() { | 
					
						
							|  |  |  | 			if d.Name() == r.Name { | 
					
						
							|  |  |  | 				continue OUTER | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		missing = append(missing, r.Name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(missing) > 0 { | 
					
						
							|  |  |  | 		return errors.Errorf("found in Chart.yaml, but missing in charts/ directory: %s", strings.Join(missing, ", ")) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LocateChart looks for a chart directory in known places, and returns either the full path or an error.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This does not ensure that the chart is well-formed; only that the requested filename exists.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Order of resolution:
 | 
					
						
							|  |  |  | // - relative to current working directory
 | 
					
						
							|  |  |  | // - if path is absolute or begins with '.', error out here
 | 
					
						
							|  |  |  | // - URL
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-08-27 01:21:52 +08:00
										 |  |  | // If 'verify' was set on ChartPathOptions, this will attempt to also verify the chart.
 | 
					
						
							| 
									
										
										
										
											2019-08-23 14:31:50 +08:00
										 |  |  | func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (string, error) { | 
					
						
							| 
									
										
										
										
											2022-01-13 10:26:41 +08:00
										 |  |  | 	if registry.IsOCI(name) && c.registryClient == nil { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("unable to lookup chart %q, missing registry client", name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	name = strings.TrimSpace(name) | 
					
						
							|  |  |  | 	version := strings.TrimSpace(c.Version) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, err := os.Stat(name); err == nil { | 
					
						
							|  |  |  | 		abs, err := filepath.Abs(name) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return abs, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if c.Verify { | 
					
						
							|  |  |  | 			if _, err := downloader.VerifyChart(abs, c.Keyring); err != nil { | 
					
						
							|  |  |  | 				return "", err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return abs, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if filepath.IsAbs(name) || strings.HasPrefix(name, ".") { | 
					
						
							|  |  |  | 		return name, errors.Errorf("path %q not found", name) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dl := downloader.ChartDownloader{ | 
					
						
							| 
									
										
										
										
											2019-01-14 16:11:21 +08:00
										 |  |  | 		Out:     os.Stdout, | 
					
						
							|  |  |  | 		Keyring: c.Keyring, | 
					
						
							|  |  |  | 		Getters: getter.All(settings), | 
					
						
							| 
									
										
										
										
											2019-06-20 05:59:07 +08:00
										 |  |  | 		Options: []getter.Option{ | 
					
						
							| 
									
										
										
										
											2021-06-12 02:36:55 +08:00
										 |  |  | 			getter.WithPassCredentialsAll(c.PassCredentialsAll), | 
					
						
							| 
									
										
										
										
											2019-12-05 23:21:58 +08:00
										 |  |  | 			getter.WithTLSClientConfig(c.CertFile, c.KeyFile, c.CaFile), | 
					
						
							| 
									
										
										
										
											2020-05-01 20:57:36 +08:00
										 |  |  | 			getter.WithInsecureSkipVerifyTLS(c.InsecureSkipTLSverify), | 
					
						
							| 
									
										
										
										
											2023-06-07 14:24:02 +08:00
										 |  |  | 			getter.WithPlainHTTP(c.PlainHTTP), | 
					
						
							| 
									
										
										
										
											2024-02-05 21:54:21 +08:00
										 |  |  | 			getter.WithBasicAuth(c.Username, c.Password), | 
					
						
							| 
									
										
										
										
											2019-06-20 05:59:07 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-08-28 18:26:21 +08:00
										 |  |  | 		RepositoryConfig: settings.RepositoryConfig, | 
					
						
							|  |  |  | 		RepositoryCache:  settings.RepositoryCache, | 
					
						
							| 
									
										
										
										
											2022-01-13 10:26:41 +08:00
										 |  |  | 		RegistryClient:   c.registryClient, | 
					
						
							| 
									
										
										
										
											2021-06-08 13:45:40 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 12:29:00 +08:00
										 |  |  | 	if registry.IsOCI(name) { | 
					
						
							|  |  |  | 		dl.Options = append(dl.Options, getter.WithRegistryClient(c.registryClient)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	if c.Verify { | 
					
						
							|  |  |  | 		dl.Verify = downloader.VerifyAlways | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.RepoURL != "" { | 
					
						
							| 
									
										
										
										
											2024-12-28 14:07:27 +08:00
										 |  |  | 		chartURL, err := repo.FindChartInRepoURL( | 
					
						
							|  |  |  | 			c.RepoURL, | 
					
						
							|  |  |  | 			name, | 
					
						
							|  |  |  | 			getter.All(settings), | 
					
						
							| 
									
										
										
										
											2025-01-25 12:38:12 +08:00
										 |  |  | 			repo.WithChartVersion(version), | 
					
						
							|  |  |  | 			repo.WithClientTLS(c.CertFile, c.KeyFile, c.CaFile), | 
					
						
							| 
									
										
										
										
											2024-12-28 14:07:27 +08:00
										 |  |  | 			repo.WithUsernamePassword(c.Username, c.Password), | 
					
						
							|  |  |  | 			repo.WithInsecureSkipTLSverify(c.InsecureSkipTLSverify), | 
					
						
							|  |  |  | 			repo.WithPassCredentialsAll(c.PassCredentialsAll), | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		name = chartURL | 
					
						
							| 
									
										
										
										
											2021-06-12 02:36:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Only pass the user/pass on when the user has said to or when the
 | 
					
						
							|  |  |  | 		// location of the chart repo and the chart are the same domain.
 | 
					
						
							|  |  |  | 		u1, err := url.Parse(c.RepoURL) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		u2, err := url.Parse(chartURL) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Host on URL (returned from url.Parse) contains the port if present.
 | 
					
						
							|  |  |  | 		// This check ensures credentials are not passed between different
 | 
					
						
							|  |  |  | 		// services on different ports.
 | 
					
						
							|  |  |  | 		if c.PassCredentialsAll || (u1.Scheme == u2.Scheme && u1.Host == u2.Host) { | 
					
						
							|  |  |  | 			dl.Options = append(dl.Options, getter.WithBasicAuth(c.Username, c.Password)) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			dl.Options = append(dl.Options, getter.WithBasicAuth("", "")) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		dl.Options = append(dl.Options, getter.WithBasicAuth(c.Username, c.Password)) | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-27 01:21:52 +08:00
										 |  |  | 	if err := os.MkdirAll(settings.RepositoryCache, 0755); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-23 14:31:50 +08:00
										 |  |  | 		return "", err | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-27 01:21:52 +08:00
										 |  |  | 	filename, _, err := dl.DownloadTo(name, version, settings.RepositoryCache) | 
					
						
							| 
									
										
										
										
											2022-04-11 17:14:26 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-04-11 16:58:48 +08:00
										 |  |  | 		return "", err | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-11 17:14:26 +08:00
										 |  |  | 	lname, err := filepath.Abs(filename) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return filename, err | 
					
						
							| 
									
										
										
										
											2020-08-27 17:45:14 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-11 17:14:26 +08:00
										 |  |  | 	return lname, nil | 
					
						
							| 
									
										
										
										
											2019-02-09 08:02:57 +08:00
										 |  |  | } |