From 75cfc39fe893ef2951cfc0e63ba05dd1378eab20 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Thu, 20 Jul 2023 18:17:28 +0800 Subject: [PATCH] feat(climc): support download helm chart --- cmd/climc/shell/k8s/repos.go | 34 ++++++++++++++++++++++++++++++++ pkg/mcclient/modules/k8s/helm.go | 27 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/cmd/climc/shell/k8s/repos.go b/cmd/climc/shell/k8s/repos.go index cc0c86bceb..c2118985e7 100644 --- a/cmd/climc/shell/k8s/repos.go +++ b/cmd/climc/shell/k8s/repos.go @@ -15,12 +15,14 @@ package k8s import ( + "io" "os" "path/filepath" "github.com/cheggaaa/pb/v3" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modules/k8s" @@ -64,4 +66,36 @@ func initRepo() { printObject(ret) return nil }) + + type DownloadOptions struct { + REPO string `help:"The name or id of helm repository` + CHART string `help:"The name of chart"` + Output string `help:"Saved file path"` + Version string `help:"The version of chart"` + } + R(new(DownloadOptions), "k8s-repo-download-chart", "Download helm chart to a file", func(s *mcclient.ClientSession, args *DownloadOptions) error { + chartFileName, src, size, err := k8s.Repos.DownloadChart(s, args.REPO, args.CHART, args.Version) + if err != nil { + return errors.Wrap(err, "download chart") + } + output := args.Output + if output == "" && chartFileName != "" { + output = chartFileName + } + if output == "" { + return errors.Errorf("--output filepath must provide") + } + f, err := os.Create(output) + if err != nil { + return errors.Wrapf(err, "create saved file: %q", args.Output) + } + defer f.Close() + var sink io.Writer = f + bar := pb.Full.Start64(size) + barReader := bar.NewProxyReader(src) + if _, err := io.Copy(sink, barReader); err != nil { + return errors.Wrap(err, "save chart") + } + return nil + }) } diff --git a/pkg/mcclient/modules/k8s/helm.go b/pkg/mcclient/modules/k8s/helm.go index 361ddbf93e..36a4f021f3 100644 --- a/pkg/mcclient/modules/k8s/helm.go +++ b/pkg/mcclient/modules/k8s/helm.go @@ -18,8 +18,11 @@ import ( "fmt" "io" "net/http" + "net/url" + "strconv" "yunion.io/x/jsonutils" + "yunion.io/x/log" "yunion.io/x/pkg/util/httputils" "yunion.io/x/onecloud/pkg/mcclient" @@ -62,3 +65,27 @@ func (m *RepoManager) UploadChart(s *mcclient.ClientSession, id string, params j } return json, nil } + +func (m *RepoManager) DownloadChart(s *mcclient.ClientSession, id string, chartName string, chartVersion string) (string, io.Reader, int64, error) { + params := map[string]string{ + "chart_name": chartName, + "version": chartVersion, + } + query := jsonutils.Marshal(params) + path := fmt.Sprintf("/%s/%s/download-chart", m.URLPath(), url.PathEscape(id)) + queryString := query.QueryString() + if len(queryString) > 0 { + path = fmt.Sprintf("%s?%s", path, queryString) + } + resp, err := modulebase.RawRequest(*m.ResourceManager.ResourceManager, s, "GET", path, nil, nil) + if err == nil && resp.StatusCode >= 200 && resp.StatusCode < 300 { + sizeBytes, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) + if err != nil { + log.Errorf("Download chart unknown size") + sizeBytes = -1 + } + return resp.Header.Get("Chart-Filename"), resp.Body, sizeBytes, nil + } + _, _, err = s.ParseJSONResponse("", resp, err) + return "", nil, -1, err +}