Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions pkg/helm/fsloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (

"helm.sh/helm/v3/pkg/chart"
chartLoader "helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/engine"
)

// LoadChart loads a Helm chart from an fs.FS at the specified path.
Expand Down Expand Up @@ -72,3 +74,40 @@ func LoadChart(resourceFS fs.FS, chartPath string) (*chart.Chart, error) {

return loadedChart, nil
}

// RenderChart renders a Helm chart's templates with the provided values.
// This does not require cluster access - it's a pure template rendering operation.
// Returns a map of template name to rendered content.
func RenderChart(resourceFS fs.FS, chartPath string, values Values, namespace, releaseName string) (map[string]string, error) {
loadedChart, err := LoadChart(resourceFS, chartPath)
if err != nil {
return nil, fmt.Errorf("failed to load chart: %w", err)
}

return RenderLoadedChart(loadedChart, values, namespace, releaseName)
}

// RenderLoadedChart renders an already-loaded chart's templates with the provided values.
// Returns a map of template name to rendered content.
func RenderLoadedChart(loadedChart *chart.Chart, values Values, namespace, releaseName string) (map[string]string, error) {
// Create release options for rendering
options := chartutil.ReleaseOptions{
Name: releaseName,
Namespace: namespace,
IsInstall: true,
}

// Merge values with chart defaults
chartValues, err := chartutil.ToRenderValues(loadedChart, values, options, nil)
if err != nil {
return nil, fmt.Errorf("failed to create render values: %w", err)
}

// Render templates
rendered, err := engine.Render(loadedChart, chartValues)
if err != nil {
return nil, fmt.Errorf("failed to render chart templates: %w", err)
}

return rendered, nil
}
32 changes: 32 additions & 0 deletions pkg/helm/fsloader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,43 @@
package helm

import (
"maps"
"os"
"strings"
"testing"
"testing/fstest"
)

func TestRenderChart(t *testing.T) {
testFS := os.DirFS("testdata")
Comment thread
nrfox marked this conversation as resolved.

t.Run("renders template with values", func(t *testing.T) {
rendered, err := RenderChart(testFS, "chart", Values{"value": "hello"}, "test-ns", "my-release")
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}

cm, ok := rendered["test-chart/templates/configmap.yaml"]
if !ok {
t.Fatalf("expected configmap template in output, got keys: %v", maps.Keys(rendered))
}

if !strings.Contains(cm, "namespace: test-ns") {
t.Errorf("expected namespace 'test-ns' in rendered output, got:\n%s", cm)
}
if !strings.Contains(cm, `value: "hello"`) {
t.Errorf("expected value 'hello' in rendered output, got:\n%s", cm)
}
})

t.Run("returns error for missing chart", func(t *testing.T) {
_, err := RenderChart(testFS, "nonexistent", nil, "ns", "rel")
if err == nil {
t.Fatal("expected error for non-existent chart path")
}
})
}

func TestLoadChart(t *testing.T) {
testFS := os.DirFS("testdata")

Expand Down
Loading