| 
									
										
										
										
											2016-06-23 02:28:45 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2018-08-25 03:03:55 +08:00
										 |  |  | Copyright The Helm Authors. | 
					
						
							| 
									
										
										
										
											2016-06-23 02:28:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-24 23:11:54 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-11-16 11:07:40 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2025-01-06 16:20:22 +08:00
										 |  |  | 	"slices" | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/spf13/cobra" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-24 23:11:54 +08:00
										 |  |  | 	"helm.sh/helm/v4/pkg/cmd/require" | 
					
						
							| 
									
										
										
										
											2024-12-27 05:33:51 +08:00
										 |  |  | 	"helm.sh/helm/v4/pkg/getter" | 
					
						
							|  |  |  | 	"helm.sh/helm/v4/pkg/repo" | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | const updateDesc = ` | 
					
						
							|  |  |  | Update gets the latest information about charts from the respective chart repositories. | 
					
						
							|  |  |  | Information is cached locally, where it is used by commands like 'helm search'. | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | You can optionally specify a list of repositories you want to update. | 
					
						
							|  |  |  | 	$ helm repo update <repo_name> ... | 
					
						
							|  |  |  | To update all the repositories, use 'helm repo update'. | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | ` | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-12 02:42:30 +08:00
										 |  |  | var errNoRepositories = errors.New("no repositories found. You must add one before updating") | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 01:30:32 +08:00
										 |  |  | type repoUpdateOptions struct { | 
					
						
							| 
									
										
										
										
											2025-03-21 20:06:01 +08:00
										 |  |  | 	update    func([]*repo.ChartRepository, io.Writer) error | 
					
						
							|  |  |  | 	repoFile  string | 
					
						
							|  |  |  | 	repoCache string | 
					
						
							|  |  |  | 	names     []string | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 02:27:44 +08:00
										 |  |  | func newRepoUpdateCmd(out io.Writer) *cobra.Command { | 
					
						
							| 
									
										
										
										
											2018-05-10 01:30:32 +08:00
										 |  |  | 	o := &repoUpdateOptions{update: updateCharts} | 
					
						
							| 
									
										
										
										
											2018-05-03 14:35:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | 	cmd := &cobra.Command{ | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 		Use:     "update [REPO1 [REPO2 ...]]", | 
					
						
							|  |  |  | 		Aliases: []string{"up"}, | 
					
						
							|  |  |  | 		Short:   "update information of available charts locally from chart repositories", | 
					
						
							|  |  |  | 		Long:    updateDesc, | 
					
						
							|  |  |  | 		Args:    require.MinimumNArgs(0), | 
					
						
							| 
									
										
										
										
											2024-03-12 05:13:34 +08:00
										 |  |  | 		ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 			return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2024-03-12 05:13:34 +08:00
										 |  |  | 		RunE: func(_ *cobra.Command, args []string) error { | 
					
						
							| 
									
										
										
										
											2019-08-27 18:55:44 +08:00
										 |  |  | 			o.repoFile = settings.RepositoryConfig | 
					
						
							| 
									
										
										
										
											2020-05-19 02:06:09 +08:00
										 |  |  | 			o.repoCache = settings.RepositoryCache | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 			o.names = args | 
					
						
							| 
									
										
										
										
											2018-05-10 01:30:32 +08:00
										 |  |  | 			return o.run(out) | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-13 20:05:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | 	return cmd | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 01:30:32 +08:00
										 |  |  | func (o *repoUpdateOptions) run(out io.Writer) error { | 
					
						
							| 
									
										
										
										
											2019-08-29 00:51:59 +08:00
										 |  |  | 	f, err := repo.LoadFile(o.repoFile) | 
					
						
							| 
									
										
										
										
											2021-02-03 03:18:01 +08:00
										 |  |  | 	switch { | 
					
						
							|  |  |  | 	case isNotExist(err): | 
					
						
							|  |  |  | 		return errNoRepositories | 
					
						
							|  |  |  | 	case err != nil: | 
					
						
							| 
									
										
										
										
											2024-11-16 11:07:40 +08:00
										 |  |  | 		return fmt.Errorf("failed loading file: %s: %w", o.repoFile, err) | 
					
						
							| 
									
										
										
										
											2021-02-03 03:18:01 +08:00
										 |  |  | 	case len(f.Repositories) == 0: | 
					
						
							| 
									
										
										
										
											2019-08-29 00:51:59 +08:00
										 |  |  | 		return errNoRepositories | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-03 03:18:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 	var repos []*repo.ChartRepository | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 	updateAllRepos := len(o.names) == 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !updateAllRepos { | 
					
						
							|  |  |  | 		// Fail early if the user specified an invalid repo to update
 | 
					
						
							|  |  |  | 		if err := checkRequestedRepos(o.names, f.Repositories); err != nil { | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, cfg := range f.Repositories { | 
					
						
							|  |  |  | 		if updateAllRepos || isRepoRequested(cfg.Name, o.names) { | 
					
						
							|  |  |  | 			r, err := repo.NewChartRepository(cfg, getter.All(settings)) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if o.repoCache != "" { | 
					
						
							|  |  |  | 				r.CachePath = o.repoCache | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			repos = append(repos, r) | 
					
						
							| 
									
										
										
										
											2020-05-19 02:06:09 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-05-17 02:51:11 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 20:06:01 +08:00
										 |  |  | 	return o.update(repos, out) | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 20:06:01 +08:00
										 |  |  | func updateCharts(repos []*repo.ChartRepository, out io.Writer) error { | 
					
						
							| 
									
										
										
										
											2016-08-26 06:55:36 +08:00
										 |  |  | 	fmt.Fprintln(out, "Hang tight while we grab the latest from your chart repositories...") | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							| 
									
										
										
										
											2025-04-05 22:47:25 +08:00
										 |  |  | 	failRepoURLChan := make(chan string, len(repos)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-28 01:39:35 +08:00
										 |  |  | 	writeMutex := sync.Mutex{} | 
					
						
							| 
									
										
										
										
											2016-09-29 08:51:12 +08:00
										 |  |  | 	for _, re := range repos { | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 		wg.Add(1) | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 		go func(re *repo.ChartRepository) { | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2019-08-23 14:31:50 +08:00
										 |  |  | 			if _, err := re.DownloadIndexFile(); err != nil { | 
					
						
							| 
									
										
										
										
											2025-05-28 01:39:35 +08:00
										 |  |  | 				writeMutex.Lock() | 
					
						
							|  |  |  | 				defer writeMutex.Unlock() | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 				fmt.Fprintf(out, "...Unable to get an update from the %q chart repository (%s):\n\t%s\n", re.Config.Name, re.Config.URL, err) | 
					
						
							| 
									
										
										
										
											2025-04-05 22:47:25 +08:00
										 |  |  | 				failRepoURLChan <- re.Config.URL | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2025-05-28 01:39:35 +08:00
										 |  |  | 				writeMutex.Lock() | 
					
						
							|  |  |  | 				defer writeMutex.Unlock() | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 				fmt.Fprintf(out, "...Successfully got an update from the %q chart repository\n", re.Config.Name) | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-11-23 17:17:23 +08:00
										 |  |  | 		}(re) | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-13 20:05:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-05 22:47:25 +08:00
										 |  |  | 	go func() { | 
					
						
							|  |  |  | 		wg.Wait() | 
					
						
							|  |  |  | 		close(failRepoURLChan) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var repoFailList []string | 
					
						
							|  |  |  | 	for url := range failRepoURLChan { | 
					
						
							|  |  |  | 		repoFailList = append(repoFailList, url) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-13 20:05:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-21 20:06:01 +08:00
										 |  |  | 	if len(repoFailList) > 0 { | 
					
						
							| 
									
										
										
										
											2025-04-14 16:51:55 +08:00
										 |  |  | 		return fmt.Errorf("failed to update the following repositories: %s", | 
					
						
							| 
									
										
										
										
											2022-01-18 23:56:31 +08:00
										 |  |  | 			repoFailList) | 
					
						
							| 
									
										
										
										
											2021-08-13 20:05:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 12:33:27 +08:00
										 |  |  | 	fmt.Fprintln(out, "Update Complete. ⎈Happy Helming!⎈") | 
					
						
							| 
									
										
										
										
											2021-08-13 20:05:23 +08:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2016-05-03 06:21:31 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func checkRequestedRepos(requestedRepos []string, validRepos []*repo.Entry) error { | 
					
						
							|  |  |  | 	for _, requestedRepo := range requestedRepos { | 
					
						
							|  |  |  | 		found := false | 
					
						
							|  |  |  | 		for _, repo := range validRepos { | 
					
						
							|  |  |  | 			if requestedRepo == repo.Name { | 
					
						
							|  |  |  | 				found = true | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !found { | 
					
						
							| 
									
										
										
										
											2024-11-16 11:07:40 +08:00
										 |  |  | 			return fmt.Errorf("no repositories found matching '%s'.  Nothing will be updated", requestedRepo) | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func isRepoRequested(repoName string, requestedRepos []string) bool { | 
					
						
							| 
									
										
										
										
											2025-01-06 16:20:22 +08:00
										 |  |  | 	return slices.Contains(requestedRepos, repoName) | 
					
						
							| 
									
										
										
										
											2021-06-19 03:12:39 +08:00
										 |  |  | } |