feat(cmd): Port child NOTES.txt rendering to Helm 3 (#6512)

* Port Helm 2 PR 4088 to Helm 3

Not a direct port as is but refactored for Helm 3.

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>

* Update unit test to test string retunred for different order

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>
pull/6549/head
Martin Hickey 5 years ago committed by GitHub
parent db15a6f898
commit 26dacf84aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -141,10 +141,11 @@ func addInstallFlags(f *pflag.FlagSet, client *action.Install, valueOpts *values
f.BoolVar(&client.Wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVarP(&client.GenerateName, "generate-name", "g", false, "generate the name (and omit the NAME parameter)")
f.StringVar(&client.NameTemplate, "name-template", "", "specify template used to name the release")
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored")
f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "run helm dependency update before installing the chart")
f.BoolVar(&client.Atomic, "atomic", false, "if set, installation process purges chart on fail. The --wait flag will be set automatically if --atomic is used")
f.BoolVar(&client.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed. By default, CRDs are installed if not already present.")
f.BoolVar(&client.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed. By default, CRDs are installed if not already present")
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")
addValueOptionsFlags(f, valueOpts)
addChartPathOptionsFlags(f, &client.ChartPathOptions)
}

@ -155,7 +155,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags()
f.BoolVarP(&client.Install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored")
f.BoolVar(&client.DryRun, "dry-run", false, "simulate an upgrade")
f.BoolVar(&client.Recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.MarkDeprecated("recreate-pods", "functionality will no longer be updated. Consult the documentation for other methods to recreate pods")
@ -163,11 +163,12 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVar(&client.DisableHooks, "no-hooks", false, "disable pre/post upgrade hooks")
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&client.ResetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&client.ReuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored.")
f.BoolVar(&client.ReuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored")
f.BoolVar(&client.Wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&client.Atomic, "atomic", false, "if set, upgrade process rolls back changes made in case of failed upgrade. The --wait flag will be set automatically if --atomic is used")
f.IntVar(&client.MaxHistory, "history-max", 10, "limit the maximum number of revisions saved per release. Use 0 for no limit.")
f.IntVar(&client.MaxHistory, "history-max", 10, "limit the maximum number of revisions saved per release. Use 0 for no limit")
f.BoolVar(&client.CleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this upgrade when upgrade fails")
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")
addChartPathOptionsFlags(f, &client.ChartPathOptions)
addValueOptionsFlags(f, valueOpts)
bindOutputFlag(cmd, &client.OutputFormat)

@ -83,6 +83,7 @@ type Install struct {
Atomic bool
SkipCRDs bool
OutputFormat string
SubNotes bool
}
// ChartPathOptions captures common options used for controlling chart paths
@ -204,7 +205,7 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
rel := i.createRelease(chrt, vals)
var manifestDoc *bytes.Buffer
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir)
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir, i.SubNotes)
// Even for errors, attach this if available
if manifestDoc != nil {
rel.Manifest = manifestDoc.String()
@ -390,7 +391,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, outputDir string) ([]*release.Hook, *bytes.Buffer, string, error) {
func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values, outputDir string, subNotes bool) ([]*release.Hook, *bytes.Buffer, string, error) {
hs := []*release.Hook{}
b := bytes.NewBuffer(nil)
@ -415,17 +416,20 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values
// text file. We have to spin through this map because the file contains path information, so we
// look for terminating NOTES.txt. We also remove it from the files so that we don't have to skip
// it in the sortHooks.
notes := ""
var notesBuffer bytes.Buffer
for k, v := range files {
if strings.HasSuffix(k, notesFileSuffix) {
// Only apply the notes if it belongs to the parent chart
// Note: Do not use filePath.Join since it creates a path with \ which is not expected
if k == path.Join(ch.Name(), "templates", notesFileSuffix) {
notes = v
if subNotes || (k == path.Join(ch.Name(), "templates", notesFileSuffix)) {
// If buffer contains data, add newline before adding more
if notesBuffer.Len() > 0 {
notesBuffer.WriteString("\n")
}
notesBuffer.WriteString(v)
}
delete(files, k)
}
}
notes := notesBuffer.String()
// Sort hooks, manifests, and partials. Only hooks and manifests are returned,
// as partials are not used after renderer.Render. Empty manifests are also

@ -23,6 +23,7 @@ import (
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@ -167,7 +168,7 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) {
is.Equal(rel.Info.Description, "Install complete")
}
func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) {
func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t)
instAction := installAction(t)
@ -185,6 +186,28 @@ func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) {
is.Equal(rel.Info.Description, "Install complete")
}
func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
instAction.SubNotes = true
vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(withNotes("parent"), withDependency(withNotes("child"))), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
}
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.Equal("with-notes", rel.Name)
is.NoError(err)
// test run can return as either 'parent\nchild' or 'child\nparent'
if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") {
t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes)
}
is.Equal(rel.Info.Description, "Install complete")
}
func TestInstallRelease_DryRun(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)

@ -57,6 +57,7 @@ type Upgrade struct {
Atomic bool
CleanupOnFail bool
OutputFormat string
SubNotes bool
}
// NewUpgrade creates a new Upgrade object with the given configuration.
@ -165,7 +166,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
return nil, nil, err
}
hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender, "")
hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender, "", u.SubNotes)
if err != nil {
return nil, nil, err
}

Loading…
Cancel
Save