diff --git a/internal/installer/installer.go b/internal/installer/installer.go index 7ed2e7ef..b1da37c0 100644 --- a/internal/installer/installer.go +++ b/internal/installer/installer.go @@ -75,6 +75,13 @@ func (i *Installer) PrintValues() { printer.ValuesPrinter("Values", i.values) } +// SetRenderedValues sets pre-rendered values directly, bypassing template +// rendering and YAML parsing. +func (i *Installer) SetRenderedValues(renderedBytes []byte, values chartutil.Values) { + i.valuesBytes = renderedBytes + i.values = values +} + // Install performs the installation of the Helm chart. func (i *Installer) Install(ctx context.Context) error { if i.values == nil { diff --git a/internal/installer/installer_test.go b/internal/installer/installer_test.go new file mode 100644 index 00000000..9337e943 --- /dev/null +++ b/internal/installer/installer_test.go @@ -0,0 +1,80 @@ +package installer + +import ( + "bytes" + "fmt" + "io" + "log/slog" + "os" + "testing" + + "github.com/redhat-appstudio/helmet/internal/flags" + "github.com/redhat-appstudio/helmet/internal/resolver" + + o "github.com/onsi/gomega" + "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chartutil" +) + +func newTestInstaller() *Installer { + dep := resolver.NewDependencyWithNamespace( + &chart.Chart{Metadata: &chart.Metadata{Name: "test-chart"}}, + "test-ns", + ) + logger := slog.New(slog.NewTextHandler(io.Discard, nil)) + return NewInstaller(logger, flags.NewFlags(), nil, dep, nil) +} + +func TestSetRenderedValues(t *testing.T) { + g := o.NewWithT(t) + + i := newTestInstaller() + + inputBytes := []byte("key: value\n") + inputValues := chartutil.Values{"key": "value"} + + i.SetRenderedValues(inputBytes, inputValues) + + g.Expect(i.valuesBytes).To(o.Equal(inputBytes)) + g.Expect(i.values).To(o.Equal(inputValues)) +} + +func TestSetRenderedValues_PrintRawValues(t *testing.T) { + g := o.NewWithT(t) + + i := newTestInstaller() + + inputBytes := []byte("key: value\n") + inputValues := chartutil.Values{"key": "value"} + i.SetRenderedValues(inputBytes, inputValues) + + old := os.Stdout + r, w, err := os.Pipe() + g.Expect(err).To(o.Succeed()) + t.Cleanup(func() { + os.Stdout = old + _ = r.Close() + _ = w.Close() + }) + + os.Stdout = w + i.PrintRawValues() + os.Stdout = old + g.Expect(w.Close()).To(o.Succeed()) + + var buf bytes.Buffer + _, err = io.Copy(&buf, r) + g.Expect(err).To(o.Succeed()) + + g.Expect(buf.String()).To(o.ContainSubstring("key: value")) +} + +func TestRenderValues_RequiresSetValues(t *testing.T) { + g := o.NewWithT(t) + + i := newTestInstaller() + + err := i.RenderValues() + g.Expect(err).To(o.HaveOccurred()) + g.Expect(err).To(o.MatchError(fmt.Errorf("values not set"))) +} diff --git a/internal/subcmd/deploy.go b/internal/subcmd/deploy.go index 7e592522..0686460e 100644 --- a/internal/subcmd/deploy.go +++ b/internal/subcmd/deploy.go @@ -8,14 +8,17 @@ import ( "github.com/redhat-appstudio/helmet/api" "github.com/redhat-appstudio/helmet/internal/config" + "github.com/redhat-appstudio/helmet/internal/engine" "github.com/redhat-appstudio/helmet/internal/flags" "github.com/redhat-appstudio/helmet/internal/installer" "github.com/redhat-appstudio/helmet/internal/integrations" "github.com/redhat-appstudio/helmet/internal/k8s" + "github.com/redhat-appstudio/helmet/internal/printer" "github.com/redhat-appstudio/helmet/internal/resolver" "github.com/redhat-appstudio/helmet/internal/runcontext" "github.com/spf13/cobra" + "helm.sh/helm/v3/pkg/chartutil" ) // Deploy is the deploy subcommand. @@ -116,6 +119,39 @@ subcommand to configure them. For example: deps = append(deps, *dep) } + ctx := d.cmd.Context() + + d.log().Debug("Preparing values template context") + variables := engine.NewVariables() + if err = variables.SetInstaller(d.cfg); err != nil { + return err + } + if err = variables.SetOpenShift(ctx, d.runCtx.Kube); err != nil { + return err + } + + d.log().Debug("Rendering values template") + renderedBytes, err := engine.NewEngine(d.runCtx.Kube, string(valuesTmpl)). + Render(variables) + if err != nil { + return err + } + + if d.flags.Verbose { + d.log().Debug("Showing raw results of rendered values template") + fmt.Printf("#\n# Values (Raw)\n#\n\n%s\n", renderedBytes) + } + + d.log().Debug("Parsing rendered values") + values, err := chartutil.ReadValues(renderedBytes) + if err != nil { + return err + } + + if d.flags.Verbose { + printer.ValuesPrinter("Values", values) + } + for index, dep := range deps { fmt.Printf("\n\n%s\n", strings.Repeat("#", 60)) fmt.Printf( @@ -128,22 +164,7 @@ subcommand to configure them. For example: fmt.Printf("%s\n", strings.Repeat("#", 60)) i := installer.NewInstaller(d.log(), d.flags, d.runCtx.Kube, &dep, d.installerTarball) - - ctx := d.cmd.Context() - err := i.SetValues(ctx, d.cfg, string(valuesTmpl)) - if err != nil { - return err - } - if d.flags.Verbose { - i.PrintRawValues() - } - - if err := i.RenderValues(); err != nil { - return err - } - if d.flags.Verbose { - i.PrintValues() - } + i.SetRenderedValues(renderedBytes, values) if err = i.Install(ctx); err != nil { return err