diff --git a/utils/kubernetes/get-manifests.go b/utils/kubernetes/get-manifests.go index 29fbb6e9..dc44b5d1 100644 --- a/utils/kubernetes/get-manifests.go +++ b/utils/kubernetes/get-manifests.go @@ -1,23 +1,90 @@ package kubernetes import ( + "fmt" "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/chartutil" + "helm.sh/helm/v3/pkg/engine" + "sort" + "strings" ) +// GetManifestsFromHelm fetches the chart, loads it, and renders templates + CRDs func GetManifestsFromHelm(url string) (string, error) { chartLocation, err := fetchHelmChart(url, "") if err != nil { - return "", ErrApplyHelmChart(err) + return "", ErrApplyHelmChart(fmt.Errorf("failed to fetch helm chart: %w", err)) } chart, err := loader.Load(chartLocation) if err != nil { - return "", ErrApplyHelmChart(err) + return "", ErrApplyHelmChart(fmt.Errorf("failed to load chart from %s: %w", chartLocation, err)) } - manifests := "" + + releaseOptions := chartutil.ReleaseOptions{ + Name: "meshery-helm-release", + Namespace: "default", + Revision: 1, + IsInstall: true, + } + + caps := chartutil.DefaultCapabilities + + values, err := chartutil.ToRenderValues(chart, chartutil.Values{}, releaseOptions, caps) + if err != nil { + return "", ErrApplyHelmChart(fmt.Errorf("failed to generate render values: %w", err)) + } + + renderedFiles, err := engine.Render(chart, values) + if err != nil { + return "", ErrApplyHelmChart(fmt.Errorf("failed to render chart templates: %w", err)) + } + + var b strings.Builder + + // Helper to safely append separators + appendSeparator := func() { + if b.Len() > 0 { + // 1. Check if the buffer ends with a newline. + // 2. If not, add one to ensure "---" starts on a fresh line. + if !strings.HasSuffix(b.String(), "\n") { + b.WriteString("\n") + } + b.WriteString("---\n") + } + } + // Append CRDs for _, crdobject := range chart.CRDObjects() { - manifests += "\n---\n" - manifests += string(crdobject.File.Data) + appendSeparator() + b.Write(crdobject.File.Data) + } + + keys := make([]string, 0, len(renderedFiles)) + for k := range renderedFiles { + keys = append(keys, k) + } + sort.Strings(keys) + + // Append Rendered Templates + for _, filename := range keys { + fileContent := renderedFiles[filename] + // Filter out non-manifest files + if strings.HasSuffix(filename, "NOTES.txt") || strings.Contains(filename, "/tests/") { + continue + } + if strings.TrimSpace(fileContent) == "" { + continue + } + + appendSeparator() + b.WriteString(fileContent) } + + manifests := b.String() + + if strings.TrimSpace(manifests) == "" { + return "", ErrApplyHelmChart(fmt.Errorf("chart rendered empty manifests")) + } + return manifests, nil } diff --git a/utils/manifests/getComponents.go b/utils/manifests/getComponents.go index c8deaaa8..a71d5303 100644 --- a/utils/manifests/getComponents.go +++ b/utils/manifests/getComponents.go @@ -3,13 +3,11 @@ package manifests import ( "context" "encoding/json" - "io" - "strings" - - "gopkg.in/yaml.v3" - "github.com/meshery/meshkit/utils" k8s "github.com/meshery/meshkit/utils/kubernetes" + "gopkg.in/yaml.v3" + "io" + "strings" ) func GetFromManifest(ctx context.Context, url string, resource int, cfg Config) (*Component, error) { @@ -41,6 +39,9 @@ func GetCrdsFromHelm(url string) ([]string, error) { if err != nil { return nil, err } + + manifest = repairYaml(manifest) + dec := yaml.NewDecoder(strings.NewReader(manifest)) var mans []string for { @@ -61,10 +62,24 @@ func GetCrdsFromHelm(url string) ([]string, error) { return removeNonCrdValues(mans), nil } +func repairYaml(doc string) string { + fixed := strings.ReplaceAll(doc, "\napiVersion:", "\n---\napiVersion:") + for strings.Contains(fixed, "\n---\n---\n") { + fixed = strings.ReplaceAll(fixed, "\n---\n---\n", "\n---\n") + } + + return fixed +} + func removeNonCrdValues(crds []string) []string { out := make([]string, 0) for _, crd := range crds { - if crd != "" && crd != " " && crd != "null" { + var crdMap map[string]interface{} + if err := json.Unmarshal([]byte(crd), &crdMap); err != nil { + continue + } + + if crdMap["kind"] == "CustomResourceDefinition" { out = append(out, crd) } }