Merge pull request #5762 from torstenwalter/output-dir

support --output-dir option for helm3 template
pull/5841/head
Martin Hickey 5 years ago committed by GitHub
commit d6b3e06506
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -23,6 +23,7 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"helm.sh/helm/cmd/helm/require"
"helm.sh/helm/pkg/action"
@ -77,6 +78,11 @@ func newTemplateCmd(out io.Writer) *cobra.Command {
}
addInstallFlags(cmd.Flags(), client)
addTemplateFlags(cmd.Flags(), client)
return cmd
}
func addTemplateFlags(f *pflag.FlagSet, client *action.Install) {
f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
}

@ -61,6 +61,8 @@ const releaseNameMaxLen = 53
// since there can be filepath in front of it.
const notesFileSuffix = "NOTES.txt"
const defaultDirectoryPermission = 0755
// Install performs an installation operation.
type Install struct {
cfg *Configuration
@ -79,6 +81,7 @@ type Install struct {
ReleaseName string
GenerateName bool
NameTemplate string
OutputDir string
}
type ValueOptions struct {
@ -132,7 +135,7 @@ func (i *Install) Run(chrt *chart.Chart) (*release.Release, error) {
rel := i.createRelease(chrt, i.rawValues)
var manifestDoc *bytes.Buffer
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender)
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir)
// Even for errors, attach this if available
if manifestDoc != nil {
rel.Manifest = manifestDoc.String()
@ -305,7 +308,7 @@ func (i *Install) replaceRelease(rel *release.Release) error {
}
// renderResources renders the templates in a chart
func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values) ([]*release.Hook, *bytes.Buffer, string, error) {
func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values, outputDir string) ([]*release.Hook, *bytes.Buffer, string, error) {
hs := []*release.Hook{}
b := bytes.NewBuffer(nil)
@ -363,12 +366,56 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values
// Aggregate all valid manifests into one big doc.
for _, m := range manifests {
fmt.Fprintf(b, "---\n# Source: %s\n%s\n", m.Name, m.Content)
if outputDir == "" {
fmt.Fprintf(b, "---\n# Source: %s\n%s\n", m.Name, m.Content)
} else {
err = writeToFile(outputDir, m.Name, m.Content)
if err != nil {
return hs, b, "", err
}
}
}
return hs, b, notes, nil
}
// write the <data> to <output-dir>/<name>
func writeToFile(outputDir string, name string, data string) error {
outfileName := strings.Join([]string{outputDir, name}, string(filepath.Separator))
err := ensureDirectoryForFile(outfileName)
if err != nil {
return err
}
f, err := os.Create(outfileName)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(fmt.Sprintf("---\n# Source: %s\n%s", name, data))
if err != nil {
return err
}
fmt.Printf("wrote %s\n", outfileName)
return nil
}
// check if the directory exists to create file. creates if don't exists
func ensureDirectoryForFile(file string) error {
baseDir := path.Dir(file)
_, err := os.Stat(baseDir)
if err != nil && !os.IsNotExist(err) {
return err
}
return os.MkdirAll(baseDir, defaultDirectoryPermission)
}
// validateManifest checks to see whether the given manifest is valid for the current Kubernetes
func (i *Install) validateManifest(manifest io.Reader) error {
_, err := i.cfg.KubeClient.BuildUnstructured(manifest)

@ -18,6 +18,10 @@ package action
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"reflect"
"regexp"
"testing"
@ -354,3 +358,34 @@ func TestMergeValues(t *testing.T) {
t.Errorf("Expected a map with different keys to merge properly with another map. Expected: %v, got %v", expectedMap, testMap)
}
}
func TestInstallReleaseOutputDir(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.rawValues = map[string]interface{}{}
dir, err := ioutil.TempDir("", "output-dir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
instAction.OutputDir = dir
_, err = instAction.Run(buildChart(withSampleTemplates()))
if err != nil {
t.Fatalf("Failed install: %s", err)
}
_, err = os.Stat(filepath.Join(dir, "hello/templates/goodbye"))
is.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/hello"))
is.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/with-partials"))
is.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/empty"))
is.True(os.IsNotExist(err))
}

@ -159,7 +159,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart) (*release.Rele
return nil, nil, err
}
hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender)
hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender, "")
if err != nil {
return nil, nil, err
}

Loading…
Cancel
Save