diff --git a/pkg/apiserver/domain/service/helm.go b/pkg/apiserver/domain/service/helm.go index 2970968e0..4e0539cf7 100644 --- a/pkg/apiserver/domain/service/helm.go +++ b/pkg/apiserver/domain/service/helm.go @@ -47,6 +47,7 @@ type HelmService interface { ListChartVersions(ctx context.Context, url string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error) GetChartValues(ctx context.Context, url string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]string, error) ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error) + DeprecatedGetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error) } type defaultHelmImpl struct { @@ -116,7 +117,29 @@ func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, cha klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error()) return nil, bcode.ErrGetChartValues } - return v, nil + return v.Data, nil +} + +func (d defaultHelmImpl) DeprecatedGetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error) { + if !utils.IsValidURL(repoURL) { + return nil, bcode.ErrRepoInvalidURL + } + var opts *common.HTTPOption + var err error + if len(secretName) != 0 { + opts, err = helm.SetHTTPOption(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) + if err != nil { + return nil, bcode.ErrRepoBasicAuth + } + } + v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, repoType, opts) + if err != nil { + klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error()) + return nil, bcode.ErrGetChartValues + } + res := make(map[string]interface{}, len(v.Values)) + flattenKey("", v.Values, res) + return res, nil } func (d defaultHelmImpl) ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error) { diff --git a/pkg/apiserver/interfaces/api/repository.go b/pkg/apiserver/interfaces/api/repository.go index e2fe0af6b..44c59e6d2 100644 --- a/pkg/apiserver/interfaces/api/repository.go +++ b/pkg/apiserver/interfaces/api/repository.go @@ -79,7 +79,7 @@ func (h repository) GetWebServiceRoute() *restful.WebService { Returns(400, "Bad Request", bcode.Bcode{}). Writes([]string{})) - ws.Route(ws.GET("/charts/{chart}/versions").To(h.listVersions). + ws.Route(ws.GET("/charts/{chart}/versions").To(h.deprecatedChartVersions). Doc("list versions").Deprecate(). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")). @@ -101,14 +101,14 @@ func (h repository) GetWebServiceRoute() *restful.WebService { Returns(400, "Bad Request", bcode.Bcode{}). Writes(map[string]string{})) - ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.chartValues). + ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.deprecatedChartValues). Doc("get chart value").Deprecate(). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")). Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")). Returns(200, "OK", map[string]interface{}{}). Returns(400, "Bad Request", bcode.Bcode{}). - Writes(map[string]string{})) + Writes(map[string]interface{}{})) ws.Route(ws.GET("/image/repos").To(h.getImageRepos). Doc("get the oci repos"). @@ -176,6 +176,50 @@ func (h repository) listVersions(req *restful.Request, res *restful.Response) { } } +func (h repository) deprecatedChartValues(req *restful.Request, res *restful.Response) { + url := req.QueryParameter("repoUrl") + secName := req.QueryParameter("secretName") + chartName := req.PathParameter("chart") + version := req.PathParameter("version") + skipCache, err := isSkipCache(req) + if err != nil { + bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter) + return + } + + values, err := h.HelmService.DeprecatedGetChartValues(req.Request.Context(), url, chartName, version, secName, "helm", skipCache) + if err != nil { + bcode.ReturnError(req, res, err) + return + } + err = res.WriteEntity(values) + if err != nil { + bcode.ReturnError(req, res, err) + return + } +} + +func (h repository) deprecatedChartVersions(req *restful.Request, res *restful.Response) { + url := req.QueryParameter("repoUrl") + chartName := req.PathParameter("chart") + secName := req.QueryParameter("secretName") + skipCache, err := isSkipCache(req) + if err != nil { + bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter) + return + } + versions, err := h.HelmService.ListChartVersions(req.Request.Context(), url, chartName, secName, skipCache) + if err != nil { + bcode.ReturnError(req, res, err) + return + } + err = res.WriteEntity(v1.ChartVersionListResponse{Versions: versions}) + if err != nil { + bcode.ReturnError(req, res, err) + return + } +} + func (h repository) chartValues(req *restful.Request, res *restful.Response) { url := req.QueryParameter("repoUrl") secName := req.QueryParameter("secretName") diff --git a/pkg/utils/helm/helm_helper.go b/pkg/utils/helm/helm_helper.go index 614ec6262..7cd28caf6 100644 --- a/pkg/utils/helm/helm_helper.go +++ b/pkg/utils/helm/helm_helper.go @@ -60,6 +60,11 @@ const ( valuesPatten = "repoUrl: %s, chart: %s, version: %s" ) +type ChartValues struct { + Data map[string]string + Values map[string]interface{} +} + // Helper provides helper functions for common Helm operations type Helper struct { cache *utils2.MemoryCacheStore @@ -313,10 +318,10 @@ func (h *Helper) ListChartsFromRepo(repoURL string, skipCache bool, opts *common } // GetValuesFromChart will extract the parameter from a helm chart -func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, repoType string, opts *common.HTTPOption) (map[string]string, error) { +func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, repoType string, opts *common.HTTPOption) (*ChartValues, error) { if h.cache != nil && !skipCache { if v := h.cache.Get(fmt.Sprintf(valuesPatten, repoURL, chartName, version)); v != nil { - return v.(map[string]string), nil + return v.(*ChartValues), nil } } if repoType == "oci" { @@ -348,7 +353,10 @@ func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version st if err != nil { continue } - v := loadValuesYamlFile(c) + v := &ChartValues{ + Data: loadValuesYamlFile(c), + Values: c.Values, + } if err != nil { return nil, err } @@ -371,7 +379,7 @@ func calculateCacheTimeFromIndex(length int) time.Duration { } // nolint -func fetchChartValuesFromOciRepo(repoURL string, chartName string, version string, opts *common.HTTPOption) (map[string]string, error) { +func fetchChartValuesFromOciRepo(repoURL string, chartName string, version string, opts *common.HTTPOption) (*ChartValues, error) { d := downloader.ChartDownloader{ Verify: downloader.VerifyNever, Getters: getter.All(cli.New()), @@ -399,7 +407,10 @@ func fetchChartValuesFromOciRepo(repoURL string, chartName string, version strin if err != nil { return nil, errors.Wrap(err, "failed to fetch values file") } - return loadValuesYamlFile(c), nil + return &ChartValues{ + Data: loadValuesYamlFile(c), + Values: c.Values, + }, nil } func loadValuesYamlFile(chart *chart.Chart) map[string]string {