From 07dbc90ffd6f4b3669b8af4b2ceecb3034402466 Mon Sep 17 00:00:00 2001 From: Bhargav Ravuri Date: Sun, 27 Jul 2025 21:00:05 +0530 Subject: [PATCH] feat(template): Add --notes flag Added flag `--notes` to `helm template` command with default set to `false`. If enabled, it will print the rendered `NOTES.txt` at the end of the manifests. If `--render-subchart-notes` (flag already exists on `template` command as it is part of `install` command's flags that `template` uses) is also enabled, the output will include the subchart's notes also. Updated the `install` command's `--render-subchart-notes` flag's description to include additional information (that it is only valid when `--notes` flag is enabled) in case of `template` command. Note: `template` command uses most of the `install` command's flags, including `--render-subchart-notes`. Updated `action.renderResources()` to format root chart's notes, and subcharts' notes if `--render-subchart-notes` flag is enabled, and return as a string based on whether it is: - Dry run, the notes are prefixed with the source filename and `---` separator. For helm install/ upgrade commands, the `--dry-run` flag can be used to enable dry run. The helm template command is considered a dry run by default. Note: The `template` command is considered a dry run by default. For eg: ``` foo NOTES HERE bar NOTES HERE baz NOTES HERE qux NOTES HERE ``` - Not a dry run, render the root chart's notes. If the `--render-subchart-notes` flag is enabled, since the subcharts' notes are also included, separate each note with a newline at the end. For eg: ``` --- # Source: foo/templates/NOTES.txt foo NOTES HERE --- # Source: foo/charts/bar/templates/NOTES.txt bar NOTES HERE --- # Source: foo/charts/baz/templates/NOTES.txt baz NOTES HERE --- # Source: foo/charts/bar/charts/qux/templates/NOTES.txt qux NOTES HERE ``` The notes in both cases are sorted based on the following 2 conditions: 1. Depth 2. Alphabetical (since the notes file's name will be the same for any chart/subchart, the order gets applied to the chart/subchart's name). Added tests for the following scenarios: - helm template: 1. On the chart without notes or subcharts 2. `--notes` on chart without notes or subcharts 3. `--render-subchart-notes` on chart without notes or subcharts 4. `--notes --render-subchart-notes` on chart without notes or subcharts 5. On the chart with notes without subcharts 6. `--notes` on chart with notes without subcharts 7. `--render-subchart-notes` on chart with notes without subcharts 8. `--notes --render-subchart-notes` on chart with notes without subcharts 9. On the chart with notes and subchart 10. `--notes` on chart with notes and subchart 11. `--render-subchart-notes` on the chart with notes and subchart 12. `--notes --render-subchart-notes` on chart with notes and subchart 13. `--help` - helm install: 1. On the chart without notes or subcharts 2. `--dry-run` on chart without notes or subcharts 3. `--render-subchart-notes` on chart without notes or subcharts 4. `--dry-run --render-subchart-notes` on chart without notes or subcharts 5. On the chart with notes without subcharts 6. `--dry-run` on chart with notes without subcharts 7. `--render-subchart-notes` on chart with notes without subcharts 8. `--dry-run --render-subchart-notes` on chart with notes without subcharts 9. On a chart with notes and subcharts 10. `--dry-run` on chart with notes and subcharts 11. `--render-subchart-notes` on chart with notes and subcharts 12. `--dry-run --render-subchart-notes` on chart with notes and subcharts 13. `--help` - helm upgrade: 1. On the chart without notes or subcharts 2. `--dry-run` on chart without notes or subcharts 3. `--render-subchart-notes` on chart without notes or subcharts 4. `--dry-run --render-subchart-notes` on chart without notes or subcharts 5. On the chart with notes without subcharts 6. `--dry-run` on chart with notes without subcharts 7. `--render-subchart-notes` on chart with notes without subcharts 8. `--dry-run --render-subchart-notes` on chart with notes without subcharts 9. On the chart with notes and subcharts 10. `--dry-run` on chart with notes and subcharts 11. `--render-subchart-notes` on chart with notes and subcharts 12. `--dry-run --render-subchart-notes` on chart with notes and subcharts 13. `--help` Related to #6901 Signed-off-by: Bhargav Ravuri --- pkg/action/action.go | 141 ++++++++++++++-- pkg/action/action_test.go | 12 +- pkg/action/install.go | 4 +- pkg/action/upgrade.go | 3 +- pkg/cmd/install.go | 16 +- pkg/cmd/install_test.go | 133 +++++++++++++++ pkg/cmd/template.go | 36 +++- pkg/cmd/template_test.go | 135 ++++++++++++++- pkg/cmd/testdata/output/install-help.txt | 159 ++++++++++++++++++ ...-run-and-render-subchart-notes-enabled.txt | 153 +++++++++++++++++ ...nd-subcharts-with-flag-dry-run-enabled.txt | 144 ++++++++++++++++ ...ith-flag-render-subchart-notes-enabled.txt | 14 ++ .../install-with-notes-and-subcharts.txt | 8 + ...l-with-notes-with-flag-dry-run-enabled.txt | 93 ++++++++++ .../testdata/output/install-with-notes.txt | 8 + ...or-subcharts-with-flag-dry-run-enabled.txt | 13 ++ .../install-without-notes-or-subcharts.txt | 7 + pkg/cmd/testdata/output/template-help.txt | 87 ++++++++++ ...otes-and-render-subchart-notes-enabled.txt | 143 ++++++++++++++++ ...-and-subcharts-with-flag-notes-enabled.txt | 134 +++++++++++++++ .../template-with-notes-and-subcharts.txt | 131 +++++++++++++++ ...ate-with-notes-with-flag-notes-enabled.txt | 83 +++++++++ .../testdata/output/template-with-notes.txt | 80 +++++++++ .../template-without-notes-or-subcharts.txt | 3 + pkg/cmd/testdata/output/upgrade-help.txt | 113 +++++++++++++ ...-run-and-render-subchart-notes-enabled.txt | 154 +++++++++++++++++ ...nd-subcharts-with-flag-dry-run-enabled.txt | 145 ++++++++++++++++ ...ith-flag-render-subchart-notes-enabled.txt | 15 ++ .../upgrade-with-notes-and-subcharts.txt | 9 + ...e-with-notes-with-flag-dry-run-enabled.txt | 94 +++++++++++ .../testdata/output/upgrade-with-notes.txt | 9 + ...or-subcharts-with-flag-dry-run-enabled.txt | 14 ++ .../upgrade-without-notes-or-subcharts.txt | 8 + .../Chart.yaml | 20 +++ .../charts/bar/Chart.yaml | 4 + .../charts/bar/charts/qux/Chart.yaml | 4 + .../charts/bar/charts/qux/templates/NOTES.txt | 1 + .../bar/charts/qux/templates/service.yaml | 15 ++ .../charts/bar/charts/qux/values.yaml | 5 + .../charts/bar/templates/NOTES.txt | 1 + .../charts/bar/templates/service.yaml | 15 ++ .../charts/bar/values.yaml | 5 + .../charts/baz/Chart.yaml | 4 + .../charts/baz/templates/NOTES.txt | 1 + .../charts/baz/templates/service.yaml | 15 ++ .../charts/baz/values.yaml | 5 + .../templates/NOTES.txt | 1 + .../templates/rbac/role.yaml | 8 + .../templates/rbac/rolebinding.yaml | 12 ++ .../templates/rbac/serviceaccount.yaml | 4 + .../templates/service.yaml | 22 +++ .../templates/tests/test-config.yaml | 8 + .../templates/tests/test-nothing.yaml | 17 ++ .../values.yaml | 5 + .../testcharts/chart-with-notes/Chart.yaml | 4 + .../chart-with-notes/templates/NOTES.txt | 1 + .../chart-with-notes/templates/rbac/role.yaml | 8 + .../templates/rbac/rolebinding.yaml | 12 ++ .../templates/rbac/serviceaccount.yaml | 4 + .../chart-with-notes/templates/service.yaml | 22 +++ .../templates/tests/test-config.yaml | 8 + .../templates/tests/test-nothing.yaml | 17 ++ .../testcharts/chart-with-notes/values.yaml | 5 + pkg/cmd/upgrade_test.go | 144 ++++++++++++++++ 64 files changed, 2669 insertions(+), 29 deletions(-) create mode 100644 pkg/cmd/testdata/output/install-help.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes-and-subcharts.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/install-with-notes.txt create mode 100644 pkg/cmd/testdata/output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/install-without-notes-or-subcharts.txt create mode 100644 pkg/cmd/testdata/output/template-help.txt create mode 100644 pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-both-flags-notes-and-render-subchart-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-flag-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/template-with-notes-and-subcharts.txt create mode 100644 pkg/cmd/testdata/output/template-with-notes-with-flag-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/template-with-notes.txt create mode 100644 pkg/cmd/testdata/output/template-without-notes-or-subcharts.txt create mode 100644 pkg/cmd/testdata/output/upgrade-help.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/upgrade-with-notes.txt create mode 100644 pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt create mode 100644 pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/NOTES.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/service.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/values.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/NOTES.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/service.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/values.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/NOTES.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/service.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/values.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/NOTES.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/role.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/rolebinding.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/serviceaccount.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/service.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-config.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-nothing.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/values.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/NOTES.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/role.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/rolebinding.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/serviceaccount.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/service.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-config.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-nothing.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-notes/values.yaml diff --git a/pkg/action/action.go b/pkg/action/action.go index 1aa9f9d19..aafb98989 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -27,6 +27,7 @@ import ( "path" "path/filepath" "slices" + "sort" "strings" "sync" "text/template" @@ -177,7 +178,9 @@ func splitAndDeannotate(postrendered string) (map[string]string, error) { // TODO: As part of the refactor the duplicate code in cmd/helm/template.go should be removed // // This code has to do with writing files to disk. -func (cfg *Configuration) renderResources(ch *chart.Chart, values common.Values, releaseName, outputDir string, subNotes, useReleaseName, includeCrds bool, pr postrenderer.PostRenderer, interactWithRemote, enableDNS, hideSecret bool) ([]*release.Hook, *bytes.Buffer, string, error) { +func (cfg *Configuration) renderResources(ch *chart.Chart, values common.Values, releaseName, outputDir string, + renderSubchartNotes, useReleaseName, includeCrds bool, pr postrenderer.PostRenderer, interactWithRemote, enableDNS, + hideSecret, isDryRun bool) ([]*release.Hook, *bytes.Buffer, string, error) { var hs []*release.Hook b := bytes.NewBuffer(nil) @@ -225,20 +228,71 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values common.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. - var notesBuffer bytes.Buffer - for k, v := range files { - if strings.HasSuffix(k, notesFileSuffix) { - 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) + // + // If --render-subchart-notes flag is enabled, the NOTES.txt files from the subcharts are also included by rendering + // engine. + notesFilePathToContent := make(map[string]string) + notesFilePaths := make([]string, 0) + for filePath, fileContent := range files { + // Filter the notes filepath(s), i.e., filepaths that end with "NOTES.txt", from all files. Note: Depending on + // the --render-subchart-notes flag, there may be more than one notes file. + if strings.HasSuffix(filePath, notesFileSuffix) { + // If --render-subchart-notes flag is enabled, add all the notes files, i.e., notes from the root chart, and + // subcharts, if any. + // + // If not enabled, select just the root chart's notes file, which will be in the format: + // /templates/NOTES.txt + if renderSubchartNotes || (filePath == path.Join(ch.Name(), "templates", notesFileSuffix)) { + // Store the notes file's (path -> content) pairs. In a dry run, the notes file names will be useful as + // the source details in the output. + // + // Since the filepaths are of already existing files, they will be unique. No checks needed. + notesFilePathToContent[filePath] = fileContent + + // Store the list of notes filepaths. The list will be used for ordering and will be sorted in the next + // steps. + notesFilePaths = append(notesFilePaths, filePath) } - delete(files, k) + + // Remove the notes files from the manifest files list. Rendered notes will be returned separately. + delete(files, filePath) } } - notes := notesBuffer.String() + + // Sort the notes filepaths based on depth first, and then in alphabetical order. Since the notes file's names are + // the same for all charts, the ordering is based on the chart names and notes filepaths. + // + // For example, for a chart and its subcharts in the hierarchy as follows: + // + // foo + // └── charts + // ├── bar + // │ └── charts + // │ └── qux + // └── baz + // + // The notes files must be sorted as follows: + // 1. foo/templates/NOTES.txt + // 2. foo/charts/bar/templates/NOTES.txt + // 3. foo/charts/baz/templates/NOTES.txt + // 4. foo/charts/bar/charts/qux/templates/NOTES.txt + sort.Slice(notesFilePaths, func(notesI, notesJ int) bool { + // Count the number of occurrences of the string "/charts/" for depth. + depth := func(s string) int { + return strings.Count(s, "/charts/") + } + + // When the depth of both charts is not the same, the smaller depth one goes first. In the above example, foo + // goes before bar and baz, and bar goes before qux. + depthI := depth(notesFilePaths[notesI]) + depthJ := depth(notesFilePaths[notesJ]) + if depthI != depthJ { + return depthI < depthJ + } + + // When both charts have the same depth, like bar and baz in the above example, use alphabetical order. + return notesFilePaths[notesI] < notesFilePaths[notesJ] + }) if pr != nil { // We need to send files to the post-renderer before sorting and splitting @@ -251,19 +305,19 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values common.Values, // Merge files as stream of documents for sending to post renderer merged, err := annotateAndMerge(files) if err != nil { - return hs, b, notes, fmt.Errorf("error merging manifests: %w", err) + return hs, b, "", fmt.Errorf("error merging manifests: %w", err) } // Run the post renderer postRendered, err := pr.Run(bytes.NewBufferString(merged)) if err != nil { - return hs, b, notes, fmt.Errorf("error while running post render on files: %w", err) + return hs, b, "", fmt.Errorf("error while running post render on files: %w", err) } // Use the file list and contents received from the post renderer files, err = splitAndDeannotate(postRendered.String()) if err != nil { - return hs, b, notes, fmt.Errorf("error while parsing post rendered output: %w", err) + return hs, b, "", fmt.Errorf("error while parsing post rendered output: %w", err) } } @@ -327,7 +381,62 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values common.Values, } } - return hs, b, notes, nil + // The rendered notes are returned as a string, which can be used in the output of the calling command. If + // --render-subchart-notes is enabled, the notes from the subcharts are also included in the output in an ordered + // manner, separated by empty lines. + // + // foo NOTES HERE + // + // bar NOTES HERE + // + // baz NOTES HERE + // + // qux NOTES HERE + // + // In a dry run, the notes are prefixed with the source file name and separator instead of an empty line as follows. + // For helm install/upgrade commands, dry run can be enabled by using the `--dry-run` flag. The helm template + // command is considered a dry run by default. However, to include notes in the helm template, the `--notes` flag + // must be enabled. + // + // --- + // # Source: foo/templates/NOTES.txt + // foo NOTES HERE + // + // If --render-subchart-notes is enabled on dry run with any of those commands, the notes from the subcharts are + // also included in the output. + // + // --- + // # Source: foo/templates/NOTES.txt + // foo NOTES HERE + // --- + // # Source: foo/charts/bar/templates/NOTES.txt + // bar NOTES HERE + // --- + // # Source: foo/charts/baz/templates/NOTES.txt + // baz NOTES HERE + // --- + // # Source: foo/charts/bar/charts/qux/templates/NOTES.txt + // qux NOTES HERE + // + // Note: The order of the notes files above is based on depth first, and then in alphabetical order. + var renderedNotes bytes.Buffer + for _, noteFilePath := range notesFilePaths { + // When dry run is enabled, add the notes file name and separator to the notes and write to the buffer. + if isDryRun { + fmt.Fprintf(&renderedNotes, "---\n# Source: %s\n%s", noteFilePath, notesFilePathToContent[noteFilePath]) + + continue + } + + // When dry run is disabled, write rendered notes to the buffer. If the buffer contains data, add a newline to + // separate from the next note. + if renderedNotes.Len() > 0 { + renderedNotes.WriteString("\n") + } + renderedNotes.WriteString(notesFilePathToContent[noteFilePath]) + } + + return hs, b, renderedNotes.String(), nil } // RESTClientGetter gets the rest client diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index 78ca01089..017d7db7b 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -788,7 +788,7 @@ func TestRenderResources_PostRenderer_Success(t *testing.T) { hooks, buf, notes, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - mockPR, false, false, false, + mockPR, false, false, false, false, ) assert.NoError(t, err) @@ -831,7 +831,7 @@ func TestRenderResources_PostRenderer_Error(t *testing.T) { _, _, _, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - mockPR, false, false, false, + mockPR, false, false, false, false, ) assert.Error(t, err) @@ -859,7 +859,7 @@ func TestRenderResources_PostRenderer_MergeError(t *testing.T) { _, _, _, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - mockPR, false, false, false, + mockPR, false, false, false, false, ) assert.Error(t, err) @@ -881,7 +881,7 @@ func TestRenderResources_PostRenderer_SplitError(t *testing.T) { _, _, _, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - mockPR, false, false, false, + mockPR, false, false, false, false, ) assert.Error(t, err) @@ -902,7 +902,7 @@ func TestRenderResources_PostRenderer_Integration(t *testing.T) { hooks, buf, notes, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - mockPR, false, false, false, + mockPR, false, false, false, false, ) assert.NoError(t, err) @@ -938,7 +938,7 @@ func TestRenderResources_NoPostRenderer(t *testing.T) { hooks, buf, notes, err := cfg.renderResources( ch, values, "test-release", "", false, false, false, - nil, false, false, false, + nil, false, false, false, false, ) assert.NoError(t, err) diff --git a/pkg/action/install.go b/pkg/action/install.go index 5ae12904d..3ba0c4379 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -342,7 +342,9 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma rel := i.createRelease(chrt, vals, i.Labels) var manifestDoc *bytes.Buffer - rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.ReleaseName, i.OutputDir, i.SubNotes, i.UseReleaseName, i.IncludeCRDs, i.PostRenderer, interactWithRemote, i.EnableDNS, i.HideSecret) + rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.ReleaseName, + i.OutputDir, i.SubNotes, i.UseReleaseName, i.IncludeCRDs, i.PostRenderer, interactWithRemote, i.EnableDNS, + i.HideSecret, i.isDryRun()) // Even for errors, attach this if available if manifestDoc != nil { rel.Manifest = manifestDoc.String() diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 3688adf0e..f60b8946e 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -284,7 +284,8 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin interactWithRemote = true } - hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender, "", "", u.SubNotes, false, false, u.PostRenderer, interactWithRemote, u.EnableDNS, u.HideSecret) + hooks, manifestDoc, notesTxt, err := u.cfg.renderResources(chart, valuesToRender, "", "", u.SubNotes, false, false, + u.PostRenderer, interactWithRemote, u.EnableDNS, u.HideSecret, u.isDryRun()) if err != nil { return nil, nil, false, err } diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index c4e121c1f..934e83b2a 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -173,7 +173,7 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { }, } - addInstallFlags(cmd, cmd.Flags(), client, valueOpts) + addInstallFlags(cmd, cmd.Flags(), client, valueOpts, false) // hide-secret is not available in all places the install flags are used so // it is added separately f := cmd.Flags() @@ -184,7 +184,8 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { return cmd } -func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Install, valueOpts *values.Options) { +func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Install, valueOpts *values.Options, + isTemplateCommand bool) { f.BoolVar(&client.CreateNamespace, "create-namespace", false, "create the release namespace if not present") // --dry-run options with expected outcome: // - Not set means no dry run and server is contacted. @@ -211,12 +212,21 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal f.BoolVar(&client.RollbackOnFailure, "rollback-on-failure", false, "if set, Helm will rollback (uninstall) the installation upon failure. The --wait flag will be default to \"watcher\" if --rollback-on-failure is set") f.MarkDeprecated("atomic", "use --rollback-on-failure instead") 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") f.BoolVar(&client.SkipSchemaValidation, "skip-schema-validation", false, "if set, disables JSON schema validation") f.StringToStringVarP(&client.Labels, "labels", "l", nil, "Labels that would be added to release metadata. Should be divided by comma.") f.BoolVar(&client.EnableDNS, "enable-dns", false, "enable DNS lookups when rendering templates") f.BoolVar(&client.HideNotes, "hide-notes", false, "if set, do not show notes in install output. Does not affect presence in chart metadata") f.BoolVar(&client.TakeOwnership, "take-ownership", false, "if set, install will ignore the check for helm annotations and take ownership of the existing resources") + + // Set the --render-subchart-notes flag description based on the command. The template command requires some + // additional information than the install/upgrade commands. + renderSubchartNotesFlagDesc := "if set, render subchart notes along with the parent" + if isTemplateCommand { + renderSubchartNotesFlagDesc = fmt.Sprintf("%s. Note: This will only work if --notes flag is enabled.", + renderSubchartNotesFlagDesc) + } + f.BoolVar(&client.SubNotes, "render-subchart-notes", false, renderSubchartNotesFlagDesc) + addValueOptionsFlags(f, valueOpts) addChartPathOptionsFlags(f, &client.ChartPathOptions) AddWaitFlag(cmd, &client.WaitStrategy) diff --git a/pkg/cmd/install_test.go b/pkg/cmd/install_test.go index f0f12e4f7..87d7cba80 100644 --- a/pkg/cmd/install_test.go +++ b/pkg/cmd/install_test.go @@ -20,10 +20,13 @@ import ( "fmt" "net/http" "net/http/httptest" + "os" "path/filepath" "testing" "helm.sh/helm/v4/pkg/repo/v1/repotest" + + "github.com/stretchr/testify/assert" ) func TestInstall(t *testing.T) { @@ -274,11 +277,141 @@ func TestInstall(t *testing.T) { wantError: true, golden: "output/install-hide-secret.txt", }, + { + // Running `helm install` on a chart that doesn't have notes or subcharts should print the install command's + // output without notes. + name: "helm install on chart without notes or subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default", emptyChart), + golden: "output/install-without-notes-or-subcharts.txt", + }, + { + // Running `helm install --dry-run` on a chart that doesn't have notes or subcharts should print the install + // command's dry-run output without notes. + name: "helm install --dry-run on chart without notes or subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run", emptyChart), + golden: "output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt", + }, + { + // Running `helm install --render-subchart-notes` on a chart that doesn't have notes or subcharts should + // print the install command's output without any notes. + name: "helm install --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --render-subchart-notes", emptyChart), + golden: "output/install-without-notes-or-subcharts.txt", + }, + { + // Running `helm install --dry-run --render-subchart-notes` on a chart that doesn't have notes or subcharts + // should print the install command's dry-run output without any notes. + name: "helm install --dry-run --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run --render-subchart-notes", emptyChart), + golden: "output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt", + }, + { + // Running `helm install` on a chart that has notes but no subcharts should print the install command's + // output with (current chart's) notes. + name: "helm install on chart with notes without subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default", chartWithNotes), + golden: "output/install-with-notes.txt", + }, + { + // Running `helm install --dry-run` on a chart that has notes but no subcharts should print the install + // command's dry-run output with (current chart's) notes. Note: The notes in dry-run output include the + // source filename and separator "---". + name: "helm install --dry-run on chart with notes without subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run", chartWithNotes), + golden: "output/install-with-notes-with-flag-dry-run-enabled.txt", + }, + { + // Running `helm install --render-subchart-notes` on a chart that has notes but no subcharts should print + // the install command's output with (current chart's) notes, i.e., no subchart's notes as no subchart. + name: "helm install --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --render-subchart-notes", chartWithNotes), + golden: "output/install-with-notes.txt", + }, + { + // Running `helm install --dry-run --render-subchart-notes` on a chart that has notes but no subcharts + // should print the install command's dry-run output (current chart's) notes, i.e., no subchart's notes as + // no subchart. Note: The notes in dry-run output include the source filename and separator "---". + name: "helm install --dry-run --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run --render-subchart-notes", + chartWithNotes), + golden: "output/install-with-notes-with-flag-dry-run-enabled.txt", + }, + { + // Running `helm install` on a chart that has notes and 2 levels of subcharts should print install command's + // output with just root chart's notes, i.e., without subchart's notes. + name: "helm install on chart with notes and subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default", chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/install-with-notes-and-subcharts.txt", + }, + { + // Running `helm install --dry-run` on a chart that has notes and 2 levels of subcharts should print the + // install command's dry-run output with just the root chart's notes, i.e., without the subchart's notes. + // sNote: The notes in dry-run output include the source filename and separator "---". + name: "helm install --dry-run on chart with notes and subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/install-with-notes-and-subcharts-with-flag-dry-run-enabled.txt", + }, + { + // Running `helm install --render-subchart-notes` on a chart that has notes and 2 levels of subcharts should + // print the install command's output with both the root chart and the subcharts' notes. + name: "helm install --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/install-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt", + }, + { + // Running `helm install --dry-run --render-subchart-notes` on a chart that has notes and 2 levels of + // subcharts should print the install command's dry-run output with both the root chart and the subcharts' + // notes. Note: The notes in dry-run output include the source filename and separator "---". + name: "helm install --dry-run --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("install luffy '%s' --namespace default --dry-run --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/" + + "install-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt", + }, } runTestCmd(t, tests) } +// TestInstallHelpOutput tests the `helm install --help` command's output text. This is required because the +// --render-subchart-notes flag's description is different for the template command from that of install/upgrade +// commands. +func TestInstallHelpOutput(t *testing.T) { + const ( + outputFilePath = "testdata/output/install-help.txt" + testNamespace = "test-namespace" + repositoryCache = "test-repository-cache-dir" + repositoryConfig = "test-repository-config.yaml" + registryConfig = "test-registry-config.json" + contentCache = "test-content-cache" + gnupgHome = "test-gpg" + commandText = "install --help" + ) + + // Reset the envs and the configs at the end of this test so that the updates wouldn’t affect other tests. + defer resetEnv()() + + // Read the expected output file. + expectedOutput, err := os.ReadFile(outputFilePath) + assert.NoError(t, err, "unexpected error while reading expected output's file %q", outputFilePath) + + // Set the configs that might otherwise change based on the local environment if not explicitly set. Note: These + // configs are not related to the current test. + settings.RepositoryCache = repositoryCache + settings.RepositoryConfig = repositoryConfig + settings.RegistryConfig = registryConfig + settings.ContentCache = contentCache + settings.SetNamespace(testNamespace) + t.Setenv("GNUPGHOME", gnupgHome) + + // Run the `helm install --help` command and compare the help text. + _, actualOutput, err := executeActionCommandC(storageFixture(), commandText) + assert.NoError(t, err, "unexpected error running command %q", commandText) + assert.Equal(t, string(expectedOutput), actualOutput, "mismatch of output") +} + func TestInstallOutputCompletion(t *testing.T) { outputFlagCompletionTest(t, "install") } diff --git a/pkg/cmd/template.go b/pkg/cmd/template.go index 81c112d51..eac9ad9e8 100644 --- a/pkg/cmd/template.go +++ b/pkg/cmd/template.go @@ -58,6 +58,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { var kubeVersion string var extraAPIs []string var showFiles []string + var renderNotes bool cmd := &cobra.Command{ Use: "template [NAME] [CHART]", @@ -136,6 +137,38 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } } + // If --notes flag is enabled, add the rendered notes file (templates/NOTES.txt) content to the output. + // Since the template command is considered a dry run, the rendered notes include the source file name + // and the separator as follows: + // + // --- + // # Source: foo/templates/NOTES.txt + // foo NOTES HERE + // + // If --render-subchart-notes flag is also enabled, the rendered notes will include notes from subcharts + // as follows: + // + // --- + // # Source: foo/templates/NOTES.txt + // foo NOTES HERE + // --- + // # Source: foo/charts/bar/templates/NOTES.txt + // bar NOTES HERE + // --- + // # Source: foo/charts/baz/templates/NOTES.txt + // baz NOTES HERE + // --- + // # Source: foo/charts/bar/charts/qux/templates/NOTES.txt + // qux NOTES HERE + // + // Note: The order of the notes files above is based on depth first, and then in alphabetical order. + // + // If just --render-subchart-notes flag is enabled and --notes flag is not, skip adding any notes to + // output. + if renderNotes { + fmt.Fprint(&manifests, rel.Info.Notes) + } + // if we have a list of files to render, then check that each of the // provided files exists in the chart. if len(showFiles) > 0 { @@ -193,7 +226,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } f := cmd.Flags() - addInstallFlags(cmd, f, client, valueOpts) + addInstallFlags(cmd, f, client, valueOpts, true) f.StringArrayVarP(&showFiles, "show-only", "s", []string{}, "only show manifests rendered from the given templates") f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout") f.BoolVar(&validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. This is the same validation performed on an install") @@ -203,6 +236,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { f.StringVar(&kubeVersion, "kube-version", "", "Kubernetes version used for Capabilities.KubeVersion") f.StringSliceVarP(&extraAPIs, "api-versions", "a", []string{}, "Kubernetes api versions used for Capabilities.APIVersions (multiple can be specified)") f.BoolVar(&client.UseReleaseName, "release-name", false, "use release name in the output-dir path.") + f.BoolVar(&renderNotes, "notes", false, "if set, render the current chart's notes file") bindPostRenderFlag(cmd, &client.PostRenderer, settings) return cmd diff --git a/pkg/cmd/template_test.go b/pkg/cmd/template_test.go index 5bcccf5d0..988612250 100644 --- a/pkg/cmd/template_test.go +++ b/pkg/cmd/template_test.go @@ -18,11 +18,19 @@ package cmd import ( "fmt" + "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) -var chartPath = "testdata/testcharts/subchart" +var ( + emptyChart = "testdata/testcharts/empty" + chartPath = "testdata/testcharts/subchart" + chartWithNotes = "testdata/testcharts/chart-with-notes" + chartWithNotesAnd2LevelsOfSubCharts = "testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts" +) func TestTemplateCmd(t *testing.T) { deletevalchart := "testdata/testcharts/issue-9027" @@ -166,10 +174,135 @@ func TestTemplateCmd(t *testing.T) { cmd: fmt.Sprintf("template '%s' -f %s/extra_values.yaml", chartPath, chartPath), golden: "output/template-subchart-cm-set-file.txt", }, + { + // Running `helm template` on a chart that doesn't have notes or subcharts should print the template + // command's output without notes. + name: "helm template on chart without notes or subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default", emptyChart), + golden: "output/template-without-notes-or-subcharts.txt", + }, + { + // Running `helm template --notes` on a chart that doesn't have notes or subcharts should print template + // command's output without notes. + name: "helm template --notes on chart without notes or subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes", emptyChart), + golden: "output/template-without-notes-or-subcharts.txt", + }, + { + // Running `helm template --render-subchart-notes` on a chart that doesn't have notes or subcharts should + // print the template command's output without notes. + name: "helm template --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --render-subchart-notes", emptyChart), + golden: "output/template-without-notes-or-subcharts.txt", + }, + { + // Running `helm template --notes --render-subchart-notes` on a chart that doesn't have notes or subcharts + // should print the template command's output without notes. + name: "helm template --notes --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes --render-subchart-notes", emptyChart), + golden: "output/template-without-notes-or-subcharts.txt", + }, + { + // Running `helm template` on a chart that has notes but no subcharts should print the template command's + // output without notes, since --notes flag is not enabled. + name: "helm template on chart with notes without subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default", chartWithNotes), + golden: "output/template-with-notes.txt", + }, + { + // Running `helm template --notes` on a chart that has notes but no subcharts should print the template + // command's output with (current chart's) notes. + name: "helm template --notes on chart with notes without subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes", chartWithNotes), + golden: "output/template-with-notes-with-flag-notes-enabled.txt", + }, + { + // Running `helm template --render-subchart-notes` on a chart that has notes but no subcharts should print + // the template command's output without notes, since --notes flag is not enabled. + name: "helm template --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --render-subchart-notes", chartWithNotes), + golden: "output/template-with-notes.txt", + }, + { + // Running `helm template --notes --render-subchart-notes` on a chart that has notes but no subcharts should + // print the template command's output (current chart's) notes, i.e., no subchart's notes as no subcharts. + name: "helm template --notes --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes --render-subchart-notes", + chartWithNotes), + golden: "output/template-with-notes-with-flag-notes-enabled.txt", + }, + { + // Running `helm template` on a chart that has notes and 2 levels of subcharts should print template + // command's output without notes, since --notes flag is not enabled. + name: "helm template on chart with notes and subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default", chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/template-with-notes-and-subcharts.txt", + }, + { + // Running `helm template --notes` on a chart that has notes and 2 levels of subcharts should print template + // command's output with just root chart's notes, i.e., no subchart's notes as no --render-subchart-notes. + name: "helm template --notes on chart with notes and subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes", chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/template-with-notes-and-subcharts-with-flag-notes-enabled.txt", + }, + { + // Running `helm template --render-subchart-notes` on a chart that has notes and 2 levels of subcharts + // should print the template command's output without notes, since --notes flag is not enabled. + name: "helm template --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/template-with-notes-and-subcharts.txt", + }, + { + // Running `helm template --notes --render-subchart-notes` on a chart that has notes and 2 levels of + // subcharts should print the template command's output with both the root chart and the subchart's notes. + name: "helm template --notes --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("template luffy '%s' --namespace default --notes --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/" + + "template-with-notes-and-subcharts-with-both-flags-notes-and-render-subchart-notes-enabled.txt", + }, } runTestCmd(t, tests) } +// TestTemplateHelpOutput tests the `helm template --help` command's output text. This is required because the +// --render-subchart-notes flag's description is different for the template command from that of install/upgrade +// commands. +func TestTemplateHelpOutput(t *testing.T) { + const ( + outputFilePath = "testdata/output/template-help.txt" + testNamespace = "test-namespace" + repositoryCache = "test-repository-cache-dir" + repositoryConfig = "test-repository-config.yaml" + registryConfig = "test-registry-config.json" + contentCache = "test-content-cache" + gnupgHome = "test-gpg" + commandText = "template --help" + ) + + // Reset the envs and the configs at the end of this test so that the updates wouldn’t affect other tests. + defer resetEnv()() + + // Read the expected output file. + expectedOutput, err := os.ReadFile(outputFilePath) + assert.NoError(t, err, "unexpected error while reading expected output's file %q", outputFilePath) + + // Set the configs that might otherwise change based on the local environment if not explicitly set. Note: These + // configs are not related to the current test. + settings.RepositoryCache = repositoryCache + settings.RepositoryConfig = repositoryConfig + settings.RegistryConfig = registryConfig + settings.ContentCache = contentCache + settings.SetNamespace(testNamespace) + t.Setenv("GNUPGHOME", gnupgHome) + + // Run the `helm template --help` command and compare the help text. + _, actualOutput, err := executeActionCommandC(storageFixture(), commandText) + assert.NoError(t, err, "unexpected error running command %q", commandText) + assert.Equal(t, string(expectedOutput), actualOutput, "mismatch of output") +} + func TestTemplateVersionCompletion(t *testing.T) { repoFile := "testdata/helmhome/helm/repositories.yaml" repoCache := "testdata/helmhome/helm/repository" diff --git a/pkg/cmd/testdata/output/install-help.txt b/pkg/cmd/testdata/output/install-help.txt new file mode 100644 index 000000000..574c5425d --- /dev/null +++ b/pkg/cmd/testdata/output/install-help.txt @@ -0,0 +1,159 @@ + +This command installs a chart archive. + +The install argument must be a chart reference, a path to a packaged chart, +a path to an unpacked chart directory or a URL. + +To override values in a chart, use either the '--values' flag and pass in a file +or use the '--set' flag and pass configuration from the command line, to force +a string value use '--set-string'. You can use '--set-file' to set individual +values from a file when the value itself is too long for the command line +or is dynamically generated. You can also use '--set-json' to set json values +(scalars/objects/arrays) from the command line. Additionally, you can use '--set-json' and passing json object as a string. + + $ helm install -f myvalues.yaml myredis ./redis + +or + + $ helm install --set name=prod myredis ./redis + +or + + $ helm install --set-string long_int=1234567890 myredis ./redis + +or + + $ helm install --set-file my_script=dothings.sh myredis ./redis + +or + + $ helm install --set-json 'master.sidecars=[{"name":"sidecar","image":"myImage","imagePullPolicy":"Always","ports":[{"name":"portname","containerPort":1234}]}]' myredis ./redis + +or + + $ helm install --set-json '{"master":{"sidecars":[{"name":"sidecar","image":"myImage","imagePullPolicy":"Always","ports":[{"name":"portname","containerPort":1234}]}]}}' myredis ./redis + +You can specify the '--values'/'-f' flag multiple times. The priority will be given to the +last (right-most) file specified. For example, if both myvalues.yaml and override.yaml +contained a key called 'Test', the value set in override.yaml would take precedence: + + $ helm install -f myvalues.yaml -f override.yaml myredis ./redis + +You can specify the '--set' flag multiple times. The priority will be given to the +last (right-most) set specified. For example, if both 'bar' and 'newbar' values are +set for a key called 'foo', the 'newbar' value would take precedence: + + $ helm install --set foo=bar --set foo=newbar myredis ./redis + +Similarly, in the following example 'foo' is set to '["four"]': + + $ helm install --set-json='foo=["one", "two", "three"]' --set-json='foo=["four"]' myredis ./redis + +And in the following example, 'foo' is set to '{"key1":"value1","key2":"bar"}': + + $ helm install --set-json='foo={"key1":"value1","key2":"value2"}' --set-json='foo.key2="bar"' myredis ./redis + +To check the generated manifests of a release without installing the chart, +the --debug and --dry-run flags can be combined. + +The --dry-run flag will output all generated chart manifests, including Secrets +which can contain sensitive values. To hide Kubernetes Secrets use the +--hide-secret flag. Please carefully consider how and when these flags are used. + +If --verify is set, the chart MUST have a provenance file, and the provenance +file MUST pass all verification steps. + +There are six different ways you can express the chart you want to install: + +1. By chart reference: helm install mymaria example/mariadb +2. By path to a packaged chart: helm install mynginx ./nginx-1.2.3.tgz +3. By path to an unpacked chart directory: helm install mynginx ./nginx +4. By absolute URL: helm install mynginx https://example.com/charts/nginx-1.2.3.tgz +5. By chart reference and repo url: helm install --repo https://example.com/charts/ mynginx nginx +6. By OCI registries: helm install mynginx --version 1.2.3 oci://example.com/charts/nginx + +CHART REFERENCES + +A chart reference is a convenient way of referencing a chart in a chart repository. + +When you use a chart reference with a repo prefix ('example/mariadb'), Helm will look in the local +configuration for a chart repository named 'example', and will then look for a +chart in that repository whose name is 'mariadb'. It will install the latest stable version of that chart +until you specify '--devel' flag to also include development version (alpha, beta, and release candidate releases), or +supply a version number with the '--version' flag. + +To see the list of chart repositories, use 'helm repo list'. To search for +charts in a repository, use 'helm search'. + +Usage: + helm install [NAME] [CHART] [flags] + +Flags: + --ca-file string verify certificates of HTTPS-enabled servers using this CA bundle + --cert-file string identify HTTPS client using this SSL certificate file + --create-namespace create the release namespace if not present + --dependency-update update dependencies if they are missing before installing the chart + --description string add a custom description + --devel use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored + --disable-openapi-validation if set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema + --dry-run string[="client"] simulate an install. If --dry-run is set with no option being specified or as '--dry-run=client', it will not attempt cluster connections. Setting '--dry-run=server' allows attempting cluster connections. + --enable-dns enable DNS lookups when rendering templates + --force-conflicts if set server-side apply will force changes against conflicts + --force-replace force resource updates by replacement + -g, --generate-name generate the name (and omit the NAME parameter) + -h, --help help for install + --hide-notes if set, do not show notes in install output. Does not affect presence in chart metadata + --hide-secret hide Kubernetes Secrets when also using the --dry-run flag + --insecure-skip-tls-verify skip tls certificate checks for the chart download + --key-file string identify HTTPS client using this SSL key file + --keyring string location of public keys used for verification (default "test-gpg/pubring.gpg") + -l, --labels stringToString Labels that would be added to release metadata. Should be divided by comma. (default []) + --name-template string specify template used to name the release + --no-hooks prevent hooks from running during install + -o, --output format prints the output in the specified format. Allowed values: table, json, yaml (default table) + --pass-credentials pass credentials to all domains + --password string chart repository password where to locate the requested chart + --plain-http use insecure HTTP connections for the chart download + --post-renderer postRendererString the name of a postrenderer type plugin to be used for post rendering. If it exists, the plugin will be used + --post-renderer-args postRendererArgsSlice an argument to the post-renderer (can specify multiple) (default []) + --render-subchart-notes if set, render subchart notes along with the parent + --replace reuse the given name, only if that name is a deleted release which remains in the history. This is unsafe in production + --repo string chart repository url where to locate the requested chart + --rollback-on-failure if set, Helm will rollback (uninstall) the installation upon failure. The --wait flag will be default to "watcher" if --rollback-on-failure is set + --server-side object updates run in the server instead of the client (default true) + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) + --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2 or using json format: {"key1": jsonval1, "key2": "jsonval2"}) + --set-literal stringArray set a literal STRING value on the command line + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + --skip-crds if set, no CRDs will be installed. By default, CRDs are installed if not already present + --skip-schema-validation if set, disables JSON schema validation + --take-ownership if set, install will ignore the check for helm annotations and take ownership of the existing resources + --timeout duration time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s) + --username string chart repository username where to locate the requested chart + -f, --values strings specify values in a YAML file or a URL (can specify multiple) + --verify verify the package before using it + --version string specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used + --wait WaitStrategy[=watcher] if specified, will wait until all resources are in the expected state before marking the operation as successful. It will wait for as long as --timeout. Valid inputs are 'watcher' and 'legacy' (default hookOnly) + --wait-for-jobs if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout + +Global Flags: + --burst-limit int client-side default throttling limit (default 100) + --color string use colored output (never, auto, always) (default "auto") + --colour string use colored output (never, auto, always) (default "auto") + --content-cache string path to the directory containing cached content (e.g. charts) (default "test-content-cache") + --debug enable verbose output + --kube-apiserver string the address and the port for the Kubernetes API server + --kube-as-group stringArray group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --kube-as-user string username to impersonate for the operation + --kube-ca-file string the certificate authority file for the Kubernetes API server connection + --kube-context string name of the kubeconfig context to use + --kube-insecure-skip-tls-verify if true, the Kubernetes API server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kube-tls-server-name string server name to use for Kubernetes API server certificate validation. If it is not provided, the hostname used to contact the server is used + --kube-token string bearer token used for authentication + --kubeconfig string path to the kubeconfig file + -n, --namespace string namespace scope for this request (default "test-namespace") + --qps float32 queries per second used when communicating with the Kubernetes API, not including bursting + --registry-config string path to the registry config file (default "test-registry-config.json") + --repository-cache string path to the directory containing cached repository indexes (default "test-repository-cache-dir") + --repository-config string path to the file containing repository names and URLs (default "test-repository-config.yaml") diff --git a/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt new file mode 100644 index 000000000..a175120ed --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt @@ -0,0 +1,153 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-install +REVISION: 1 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo +--- +# Source: foo/charts/bar/templates/NOTES.txt +Sample notes for bar +--- +# Source: foo/charts/baz/templates/NOTES.txt +Sample notes for baz +--- +# Source: foo/charts/bar/charts/qux/templates/NOTES.txt +Sample notes for qux diff --git a/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..ed8efc080 --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-dry-run-enabled.txt @@ -0,0 +1,144 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-install +REVISION: 1 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt new file mode 100644 index 000000000..8a6f6170a --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt @@ -0,0 +1,14 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +DESCRIPTION: Install complete +NOTES: +Sample notes for foo + +Sample notes for bar + +Sample notes for baz + +Sample notes for qux diff --git a/pkg/cmd/testdata/output/install-with-notes-and-subcharts.txt b/pkg/cmd/testdata/output/install-with-notes-and-subcharts.txt new file mode 100644 index 000000000..fe61729b1 --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes-and-subcharts.txt @@ -0,0 +1,8 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +DESCRIPTION: Install complete +NOTES: +Sample notes for foo diff --git a/pkg/cmd/testdata/output/install-with-notes-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/install-with-notes-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..e6a3d45a9 --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes-with-flag-dry-run-enabled.txt @@ -0,0 +1,93 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-install +REVISION: 1 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: sanji + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/install-with-notes.txt b/pkg/cmd/testdata/output/install-with-notes.txt new file mode 100644 index 000000000..fe61729b1 --- /dev/null +++ b/pkg/cmd/testdata/output/install-with-notes.txt @@ -0,0 +1,8 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +DESCRIPTION: Install complete +NOTES: +Sample notes for foo diff --git a/pkg/cmd/testdata/output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..4af46a22f --- /dev/null +++ b/pkg/cmd/testdata/output/install-without-notes-or-subcharts-with-flag-dry-run-enabled.txt @@ -0,0 +1,13 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-install +REVISION: 1 +DESCRIPTION: Dry run complete +TEST SUITE: None +HOOKS: +MANIFEST: +--- +# Source: empty/templates/empty.yaml +# This file is intentionally blank + diff --git a/pkg/cmd/testdata/output/install-without-notes-or-subcharts.txt b/pkg/cmd/testdata/output/install-without-notes-or-subcharts.txt new file mode 100644 index 000000000..5bf50e098 --- /dev/null +++ b/pkg/cmd/testdata/output/install-without-notes-or-subcharts.txt @@ -0,0 +1,7 @@ +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +DESCRIPTION: Install complete +TEST SUITE: None diff --git a/pkg/cmd/testdata/output/template-help.txt b/pkg/cmd/testdata/output/template-help.txt new file mode 100644 index 000000000..6131f89ec --- /dev/null +++ b/pkg/cmd/testdata/output/template-help.txt @@ -0,0 +1,87 @@ + +Render chart templates locally and display the output. + +Any values that would normally be looked up or retrieved in-cluster will be +faked locally. Additionally, none of the server-side testing of chart validity +(e.g. whether an API is supported) is done. + +Usage: + helm template [NAME] [CHART] [flags] + +Flags: + -a, --api-versions strings Kubernetes api versions used for Capabilities.APIVersions (multiple can be specified) + --ca-file string verify certificates of HTTPS-enabled servers using this CA bundle + --cert-file string identify HTTPS client using this SSL certificate file + --create-namespace create the release namespace if not present + --dependency-update update dependencies if they are missing before installing the chart + --description string add a custom description + --devel use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored + --disable-openapi-validation if set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema + --dry-run string[="client"] simulate an install. If --dry-run is set with no option being specified or as '--dry-run=client', it will not attempt cluster connections. Setting '--dry-run=server' allows attempting cluster connections. + --enable-dns enable DNS lookups when rendering templates + --force-conflicts if set server-side apply will force changes against conflicts + --force-replace force resource updates by replacement + -g, --generate-name generate the name (and omit the NAME parameter) + -h, --help help for template + --hide-notes if set, do not show notes in install output. Does not affect presence in chart metadata + --include-crds include CRDs in the templated output + --insecure-skip-tls-verify skip tls certificate checks for the chart download + --is-upgrade set .Release.IsUpgrade instead of .Release.IsInstall + --key-file string identify HTTPS client using this SSL key file + --keyring string location of public keys used for verification (default "test-gpg/pubring.gpg") + --kube-version string Kubernetes version used for Capabilities.KubeVersion + -l, --labels stringToString Labels that would be added to release metadata. Should be divided by comma. (default []) + --name-template string specify template used to name the release + --no-hooks prevent hooks from running during install + --notes if set, render the current chart's notes file + --output-dir string writes the executed templates to files in output-dir instead of stdout + --pass-credentials pass credentials to all domains + --password string chart repository password where to locate the requested chart + --plain-http use insecure HTTP connections for the chart download + --post-renderer postRendererString the name of a postrenderer type plugin to be used for post rendering. If it exists, the plugin will be used + --post-renderer-args postRendererArgsSlice an argument to the post-renderer (can specify multiple) (default []) + --release-name use release name in the output-dir path. + --render-subchart-notes if set, render subchart notes along with the parent. Note: This will only work if --notes flag is enabled. + --replace reuse the given name, only if that name is a deleted release which remains in the history. This is unsafe in production + --repo string chart repository url where to locate the requested chart + --rollback-on-failure if set, Helm will rollback (uninstall) the installation upon failure. The --wait flag will be default to "watcher" if --rollback-on-failure is set + --server-side object updates run in the server instead of the client (default true) + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) + --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2 or using json format: {"key1": jsonval1, "key2": "jsonval2"}) + --set-literal stringArray set a literal STRING value on the command line + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + -s, --show-only stringArray only show manifests rendered from the given templates + --skip-crds if set, no CRDs will be installed. By default, CRDs are installed if not already present + --skip-schema-validation if set, disables JSON schema validation + --skip-tests skip tests from templated output + --take-ownership if set, install will ignore the check for helm annotations and take ownership of the existing resources + --timeout duration time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s) + --username string chart repository username where to locate the requested chart + --validate validate your manifests against the Kubernetes cluster you are currently pointing at. This is the same validation performed on an install + -f, --values strings specify values in a YAML file or a URL (can specify multiple) + --verify verify the package before using it + --version string specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used + --wait WaitStrategy[=watcher] if specified, will wait until all resources are in the expected state before marking the operation as successful. It will wait for as long as --timeout. Valid inputs are 'watcher' and 'legacy' (default hookOnly) + --wait-for-jobs if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout + +Global Flags: + --burst-limit int client-side default throttling limit (default 100) + --color string use colored output (never, auto, always) (default "auto") + --colour string use colored output (never, auto, always) (default "auto") + --content-cache string path to the directory containing cached content (e.g. charts) (default "test-content-cache") + --debug enable verbose output + --kube-apiserver string the address and the port for the Kubernetes API server + --kube-as-group stringArray group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --kube-as-user string username to impersonate for the operation + --kube-ca-file string the certificate authority file for the Kubernetes API server connection + --kube-context string name of the kubeconfig context to use + --kube-insecure-skip-tls-verify if true, the Kubernetes API server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kube-tls-server-name string server name to use for Kubernetes API server certificate validation. If it is not provided, the hostname used to contact the server is used + --kube-token string bearer token used for authentication + --kubeconfig string path to the kubeconfig file + -n, --namespace string namespace scope for this request (default "test-namespace") + --qps float32 queries per second used when communicating with the Kubernetes API, not including bursting + --registry-config string path to the registry config file (default "test-registry-config.json") + --repository-cache string path to the directory containing cached repository indexes (default "test-repository-cache-dir") + --repository-config string path to the file containing repository names and URLs (default "test-repository-config.yaml") diff --git a/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-both-flags-notes-and-render-subchart-notes-enabled.txt b/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-both-flags-notes-and-render-subchart-notes-enabled.txt new file mode 100644 index 000000000..10a645872 --- /dev/null +++ b/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-both-flags-notes-and-render-subchart-notes-enabled.txt @@ -0,0 +1,143 @@ +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo +--- +# Source: foo/charts/bar/templates/NOTES.txt +Sample notes for bar +--- +# Source: foo/charts/baz/templates/NOTES.txt +Sample notes for baz +--- +# Source: foo/charts/bar/charts/qux/templates/NOTES.txt +Sample notes for qux diff --git a/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-flag-notes-enabled.txt b/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-flag-notes-enabled.txt new file mode 100644 index 000000000..b61b85e2e --- /dev/null +++ b/pkg/cmd/testdata/output/template-with-notes-and-subcharts-with-flag-notes-enabled.txt @@ -0,0 +1,134 @@ +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/template-with-notes-and-subcharts.txt b/pkg/cmd/testdata/output/template-with-notes-and-subcharts.txt new file mode 100644 index 000000000..85d4318b9 --- /dev/null +++ b/pkg/cmd/testdata/output/template-with-notes-and-subcharts.txt @@ -0,0 +1,131 @@ +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never diff --git a/pkg/cmd/testdata/output/template-with-notes-with-flag-notes-enabled.txt b/pkg/cmd/testdata/output/template-with-notes-with-flag-notes-enabled.txt new file mode 100644 index 000000000..2d06858c6 --- /dev/null +++ b/pkg/cmd/testdata/output/template-with-notes-with-flag-notes-enabled.txt @@ -0,0 +1,83 @@ +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: sanji + selector: + app.kubernetes.io/name: foo +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/template-with-notes.txt b/pkg/cmd/testdata/output/template-with-notes.txt new file mode 100644 index 000000000..7f36be847 --- /dev/null +++ b/pkg/cmd/testdata/output/template-with-notes.txt @@ -0,0 +1,80 @@ +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: sanji + selector: + app.kubernetes.io/name: foo +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never diff --git a/pkg/cmd/testdata/output/template-without-notes-or-subcharts.txt b/pkg/cmd/testdata/output/template-without-notes-or-subcharts.txt new file mode 100644 index 000000000..0642fca7f --- /dev/null +++ b/pkg/cmd/testdata/output/template-without-notes-or-subcharts.txt @@ -0,0 +1,3 @@ +--- +# Source: empty/templates/empty.yaml +# This file is intentionally blank diff --git a/pkg/cmd/testdata/output/upgrade-help.txt b/pkg/cmd/testdata/output/upgrade-help.txt new file mode 100644 index 000000000..fe8c15f2f --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-help.txt @@ -0,0 +1,113 @@ + +This command upgrades a release to a new version of a chart. + +The upgrade arguments must be a release and chart. The chart +argument can be either: a chart reference('example/mariadb'), a path to a chart directory, +a packaged chart, or a fully qualified URL. For chart references, the latest +version will be specified unless the '--version' flag is set. + +To override values in a chart, use either the '--values' flag and pass in a file +or use the '--set' flag and pass configuration from the command line, to force string +values, use '--set-string'. You can use '--set-file' to set individual +values from a file when the value itself is too long for the command line +or is dynamically generated. You can also use '--set-json' to set json values +(scalars/objects/arrays) from the command line. Additionally, you can use '--set-json' and passing json object as a string. + +You can specify the '--values'/'-f' flag multiple times. The priority will be given to the +last (right-most) file specified. For example, if both myvalues.yaml and override.yaml +contained a key called 'Test', the value set in override.yaml would take precedence: + + $ helm upgrade -f myvalues.yaml -f override.yaml redis ./redis + +You can specify the '--set' flag multiple times. The priority will be given to the +last (right-most) set specified. For example, if both 'bar' and 'newbar' values are +set for a key called 'foo', the 'newbar' value would take precedence: + + $ helm upgrade --set foo=bar --set foo=newbar redis ./redis + +You can update the values for an existing release with this command as well via the +'--reuse-values' flag. The 'RELEASE' and 'CHART' arguments should be set to the original +parameters, and existing values will be merged with any values set via '--values'/'-f' +or '--set' flags. Priority is given to new values. + + $ helm upgrade --reuse-values --set foo=bar --set foo=newbar redis ./redis + +The --dry-run flag will output all generated chart manifests, including Secrets +which can contain sensitive values. To hide Kubernetes Secrets use the +--hide-secret flag. Please carefully consider how and when these flags are used. + +Usage: + helm upgrade [RELEASE] [CHART] [flags] + +Flags: + --ca-file string verify certificates of HTTPS-enabled servers using this CA bundle + --cert-file string identify HTTPS client using this SSL certificate file + --cleanup-on-fail allow deletion of new resources created in this upgrade when upgrade fails + --create-namespace if --install is set, create the release namespace if not present + --dependency-update update dependencies if they are missing before installing the chart + --description string add a custom description + --devel use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored + --disable-openapi-validation if set, the upgrade process will not validate rendered templates against the Kubernetes OpenAPI Schema + --dry-run string[="client"] simulate an install. If --dry-run is set with no option being specified or as '--dry-run=client', it will not attempt cluster connections. Setting '--dry-run=server' allows attempting cluster connections. + --enable-dns enable DNS lookups when rendering templates + --force-conflicts if set server-side apply will force changes against conflicts + --force-replace force resource updates by replacement + -h, --help help for upgrade + --hide-notes if set, do not show notes in upgrade output. Does not affect presence in chart metadata + --hide-secret hide Kubernetes Secrets when also using the --dry-run flag + --history-max int limit the maximum number of revisions saved per release. Use 0 for no limit (default 10) + --insecure-skip-tls-verify skip tls certificate checks for the chart download + -i, --install if a release by this name doesn't already exist, run an install + --key-file string identify HTTPS client using this SSL key file + --keyring string location of public keys used for verification (default "test-gpg/pubring.gpg") + -l, --labels stringToString Labels that would be added to release metadata. Should be separated by comma. Original release labels will be merged with upgrade labels. You can unset label using null. (default []) + --no-hooks disable pre/post upgrade hooks + -o, --output format prints the output in the specified format. Allowed values: table, json, yaml (default table) + --pass-credentials pass credentials to all domains + --password string chart repository password where to locate the requested chart + --plain-http use insecure HTTP connections for the chart download + --post-renderer postRendererString the name of a postrenderer type plugin to be used for post rendering. If it exists, the plugin will be used + --post-renderer-args postRendererArgsSlice an argument to the post-renderer (can specify multiple) (default []) + --render-subchart-notes if set, render subchart notes along with the parent + --repo string chart repository url where to locate the requested chart + --reset-then-reuse-values when upgrading, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' or '--reuse-values' is specified, this is ignored + --reset-values when upgrading, reset the values to the ones built into the chart + --reuse-values 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 + --rollback-on-failure if set, Helm will rollback the upgrade to previous success release upon failure. The --wait flag will be defaulted to "watcher" if --rollback-on-failure is set + --server-side string must be "true", "false" or "auto". Object updates run in the server instead of the client ("auto" defaults the value from the previous chart release's method) (default "auto") + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) + --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2 or using json format: {"key1": jsonval1, "key2": "jsonval2"}) + --set-literal stringArray set a literal STRING value on the command line + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) + --skip-crds if set, no CRDs will be installed when an upgrade is performed with install flag enabled. By default, CRDs are installed if not already present, when an upgrade is performed with install flag enabled + --skip-schema-validation if set, disables JSON schema validation + --take-ownership if set, upgrade will ignore the check for helm annotations and take ownership of the existing resources + --timeout duration time to wait for any individual Kubernetes operation (like Jobs for hooks) (default 5m0s) + --username string chart repository username where to locate the requested chart + -f, --values strings specify values in a YAML file or a URL (can specify multiple) + --verify verify the package before using it + --version string specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used + --wait WaitStrategy[=watcher] if specified, will wait until all resources are in the expected state before marking the operation as successful. It will wait for as long as --timeout. Valid inputs are 'watcher' and 'legacy' (default hookOnly) + --wait-for-jobs if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout + +Global Flags: + --burst-limit int client-side default throttling limit (default 100) + --color string use colored output (never, auto, always) (default "auto") + --colour string use colored output (never, auto, always) (default "auto") + --content-cache string path to the directory containing cached content (e.g. charts) (default "test-content-cache") + --debug enable verbose output + --kube-apiserver string the address and the port for the Kubernetes API server + --kube-as-group stringArray group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --kube-as-user string username to impersonate for the operation + --kube-ca-file string the certificate authority file for the Kubernetes API server connection + --kube-context string name of the kubeconfig context to use + --kube-insecure-skip-tls-verify if true, the Kubernetes API server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kube-tls-server-name string server name to use for Kubernetes API server certificate validation. If it is not provided, the hostname used to contact the server is used + --kube-token string bearer token used for authentication + --kubeconfig string path to the kubeconfig file + -n, --namespace string namespace scope for this request (default "test-namespace") + --qps float32 queries per second used when communicating with the Kubernetes API, not including bursting + --registry-config string path to the registry config file (default "test-registry-config.json") + --repository-cache string path to the directory containing cached repository indexes (default "test-repository-cache-dir") + --repository-config string path to the file containing repository names and URLs (default "test-repository-config.yaml") diff --git a/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt new file mode 100644 index 000000000..42d084ba0 --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt @@ -0,0 +1,154 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-upgrade +REVISION: 2 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo +--- +# Source: foo/charts/bar/templates/NOTES.txt +Sample notes for bar +--- +# Source: foo/charts/baz/templates/NOTES.txt +Sample notes for baz +--- +# Source: foo/charts/bar/charts/qux/templates/NOTES.txt +Sample notes for qux diff --git a/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..48c3f695a --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-dry-run-enabled.txt @@ -0,0 +1,145 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-upgrade +REVISION: 2 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/charts/bar/charts/qux/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: qux + labels: + helm.sh/chart: "qux-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: usopp + selector: + app.kubernetes.io/name: qux +--- +# Source: foo/charts/bar/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: bar + labels: + helm.sh/chart: "bar-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: zoro + selector: + app.kubernetes.io/name: bar +--- +# Source: foo/charts/baz/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: baz + labels: + helm.sh/chart: "baz-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nami + selector: + app.kubernetes.io/name: baz +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: luffy + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt new file mode 100644 index 000000000..efdd97d1d --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt @@ -0,0 +1,15 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 2 +DESCRIPTION: Upgrade complete +NOTES: +Sample notes for foo + +Sample notes for bar + +Sample notes for baz + +Sample notes for qux diff --git a/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts.txt b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts.txt new file mode 100644 index 000000000..b8d69f279 --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes-and-subcharts.txt @@ -0,0 +1,9 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 2 +DESCRIPTION: Upgrade complete +NOTES: +Sample notes for foo diff --git a/pkg/cmd/testdata/output/upgrade-with-notes-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/upgrade-with-notes-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..39ed127de --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes-with-flag-dry-run-enabled.txt @@ -0,0 +1,94 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-upgrade +REVISION: 2 +DESCRIPTION: Dry run complete +HOOKS: +--- +# Source: foo/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "luffy-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: foo/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "luffy-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "luffy-testconfig" + command: + - echo + - "$message" + restartPolicy: Never +MANIFEST: +--- +# Source: foo/templates/rbac/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: foo-sa +--- +# Source: foo/templates/rbac/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: foo-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: foo/templates/rbac/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: foo-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: foo-role +subjects: +- kind: ServiceAccount + name: foo-sa + namespace: default +--- +# Source: foo/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: foo + labels: + helm.sh/chart: "foo-0.1.0" + app.kubernetes.io/instance: "luffy" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: sanji + selector: + app.kubernetes.io/name: foo + +NOTES: +--- +# Source: foo/templates/NOTES.txt +Sample notes for foo diff --git a/pkg/cmd/testdata/output/upgrade-with-notes.txt b/pkg/cmd/testdata/output/upgrade-with-notes.txt new file mode 100644 index 000000000..b8d69f279 --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-with-notes.txt @@ -0,0 +1,9 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 2 +DESCRIPTION: Upgrade complete +NOTES: +Sample notes for foo diff --git a/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt b/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt new file mode 100644 index 000000000..0c36cd9f1 --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt @@ -0,0 +1,14 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: pending-upgrade +REVISION: 2 +DESCRIPTION: Dry run complete +TEST SUITE: None +HOOKS: +MANIFEST: +--- +# Source: empty/templates/empty.yaml +# This file is intentionally blank + diff --git a/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts.txt b/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts.txt new file mode 100644 index 000000000..1ae7339eb --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-without-notes-or-subcharts.txt @@ -0,0 +1,8 @@ +Release "luffy" has been upgraded. Happy Helming! +NAME: luffy +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 2 +DESCRIPTION: Upgrade complete +TEST SUITE: None diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/Chart.yaml new file mode 100644 index 000000000..5780cb525 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +description: A Helm chart 'foo' for Kubernetes +name: foo +version: 0.1.0 +dependencies: + - name: bar + repository: http://localhost:8080 + version: 0.1.0 + condition: bar.enabled + tags: + - strawhats + - bar + + - name: baz + repository: http://localhost:8080 + version: 0.1.0 + condition: baz.enabled + tags: + - strawhats + - baz diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/Chart.yaml new file mode 100644 index 000000000..5fab6fd54 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart 'bar' for Kubernetes +name: bar +version: 0.1.0 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/Chart.yaml new file mode 100644 index 000000000..23d07f8f8 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart 'qux' for Kubernetes +name: qux +version: 0.1.0 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/NOTES.txt b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/NOTES.txt new file mode 100644 index 000000000..cfcef184a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/NOTES.txt @@ -0,0 +1 @@ +Sample notes for {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/service.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/service.yaml new file mode 100644 index 000000000..27501e1e0 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + name: {{ .Values.service.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/values.yaml new file mode 100644 index 000000000..e46247138 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/charts/qux/values.yaml @@ -0,0 +1,5 @@ +service: + name: usopp + type: ClusterIP + externalPort: 80 + internalPort: 80 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/NOTES.txt b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/NOTES.txt new file mode 100644 index 000000000..cfcef184a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/NOTES.txt @@ -0,0 +1 @@ +Sample notes for {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/service.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/service.yaml new file mode 100644 index 000000000..27501e1e0 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + name: {{ .Values.service.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/values.yaml new file mode 100644 index 000000000..b1806b5c4 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/bar/values.yaml @@ -0,0 +1,5 @@ +service: + name: zoro + type: ClusterIP + externalPort: 80 + internalPort: 80 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/Chart.yaml new file mode 100644 index 000000000..e0345a9c5 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart 'baz' for Kubernetes +name: baz +version: 0.1.0 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/NOTES.txt b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/NOTES.txt new file mode 100644 index 000000000..cfcef184a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/NOTES.txt @@ -0,0 +1 @@ +Sample notes for {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/service.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/service.yaml new file mode 100644 index 000000000..27501e1e0 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + name: {{ .Values.service.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/values.yaml new file mode 100644 index 000000000..543291eea --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/charts/baz/values.yaml @@ -0,0 +1,5 @@ +service: + name: nami + type: ClusterIP + externalPort: 80 + internalPort: 80 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/NOTES.txt b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/NOTES.txt new file mode 100644 index 000000000..cfcef184a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/NOTES.txt @@ -0,0 +1 @@ +Sample notes for {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/role.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/role.yaml new file mode 100644 index 000000000..31cff9200 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/role.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Chart.Name }}-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/rolebinding.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/rolebinding.yaml new file mode 100644 index 000000000..5d193f1a6 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/rolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Chart.Name }}-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Chart.Name }}-role +subjects: +- kind: ServiceAccount + name: {{ .Chart.Name }}-sa + namespace: default diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/serviceaccount.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/serviceaccount.yaml new file mode 100644 index 000000000..7126c7d89 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/rbac/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Chart.Name }}-sa diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/service.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/service.yaml new file mode 100644 index 000000000..fee94dced --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app.kubernetes.io/instance: "{{ .Release.Name }}" + kube-version/major: "{{ .Capabilities.KubeVersion.Major }}" + kube-version/minor: "{{ .Capabilities.KubeVersion.Minor }}" + kube-version/version: "v{{ .Capabilities.KubeVersion.Major }}.{{ .Capabilities.KubeVersion.Minor }}.0" +{{- if .Capabilities.APIVersions.Has "helm.k8s.io/test" }} + kube-api-version/test: v1 +{{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + name: {{ .Values.service.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-config.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-config.yaml new file mode 100644 index 000000000..0aa3eea29 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Release.Name }}-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-nothing.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-nothing.yaml new file mode 100644 index 000000000..0fe6dbbf3 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/templates/tests/test-nothing.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "{{ .Release.Name }}-testconfig" + command: + - echo + - "$message" + restartPolicy: Never diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/values.yaml new file mode 100644 index 000000000..0f73d7bb9 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes-and-2-levels-of-subcharts/values.yaml @@ -0,0 +1,5 @@ +service: + name: luffy + type: ClusterIP + externalPort: 80 + internalPort: 80 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/Chart.yaml new file mode 100644 index 000000000..9c48015bb --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart 'foo' for Kubernetes +name: foo +version: 0.1.0 diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/NOTES.txt b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/NOTES.txt new file mode 100644 index 000000000..cfcef184a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/NOTES.txt @@ -0,0 +1 @@ +Sample notes for {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/role.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/role.yaml new file mode 100644 index 000000000..31cff9200 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/role.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Chart.Name }}-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/rolebinding.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/rolebinding.yaml new file mode 100644 index 000000000..5d193f1a6 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/rolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Chart.Name }}-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Chart.Name }}-role +subjects: +- kind: ServiceAccount + name: {{ .Chart.Name }}-sa + namespace: default diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/serviceaccount.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/serviceaccount.yaml new file mode 100644 index 000000000..7126c7d89 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/rbac/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Chart.Name }}-sa diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/service.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/service.yaml new file mode 100644 index 000000000..fee94dced --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app.kubernetes.io/instance: "{{ .Release.Name }}" + kube-version/major: "{{ .Capabilities.KubeVersion.Major }}" + kube-version/minor: "{{ .Capabilities.KubeVersion.Minor }}" + kube-version/version: "v{{ .Capabilities.KubeVersion.Major }}.{{ .Capabilities.KubeVersion.Minor }}.0" +{{- if .Capabilities.APIVersions.Has "helm.k8s.io/test" }} + kube-api-version/test: v1 +{{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + name: {{ .Values.service.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-config.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-config.yaml new file mode 100644 index 000000000..0aa3eea29 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ .Release.Name }}-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-nothing.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-nothing.yaml new file mode 100644 index 000000000..0fe6dbbf3 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/templates/tests/test-nothing.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "{{ .Release.Name }}-testconfig" + command: + - echo + - "$message" + restartPolicy: Never diff --git a/pkg/cmd/testdata/testcharts/chart-with-notes/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-notes/values.yaml new file mode 100644 index 000000000..7ed78096e --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-notes/values.yaml @@ -0,0 +1,5 @@ +service: + name: sanji + type: ClusterIP + externalPort: 80 + internalPort: 80 diff --git a/pkg/cmd/upgrade_test.go b/pkg/cmd/upgrade_test.go index 9b17f187d..3ae6d5ec6 100644 --- a/pkg/cmd/upgrade_test.go +++ b/pkg/cmd/upgrade_test.go @@ -29,6 +29,8 @@ import ( "helm.sh/helm/v4/pkg/chart/v2/loader" chartutil "helm.sh/helm/v4/pkg/chart/v2/util" release "helm.sh/helm/v4/pkg/release/v1" + + "github.com/stretchr/testify/assert" ) func TestUpgradeCmd(t *testing.T) { @@ -188,10 +190,152 @@ func TestUpgradeCmd(t *testing.T) { golden: "output/upgrade-uninstalled-with-keep-history.txt", rels: []*release.Release{relWithStatusMock("funny-bunny", 2, ch, release.StatusUninstalled)}, }, + { + // Running `helm upgrade` on a chart that doesn't have notes or subcharts should print the upgrade command's + // output without notes. + name: "helm upgrade on chart without notes or subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default", emptyChart), + golden: "output/upgrade-without-notes-or-subcharts.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run` on a chart that doesn't have notes or subcharts should print upgrade + // command's dry-run output without notes. + name: "helm upgrade --dry-run on chart without notes or subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run", emptyChart), + golden: "output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --render-subchart-notes` on a chart that doesn't have notes or subcharts should + // print the upgrade command's output without any notes. + name: "helm upgrade --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --render-subchart-notes", emptyChart), + golden: "output/upgrade-without-notes-or-subcharts.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run --render-subchart-notes` on a chart that doesn't have notes or subcharts + // should print the upgrade command's dry-run output without any notes. + name: "helm upgrade --dry-run --render-subchart-notes on chart without notes or subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run --render-subchart-notes", emptyChart), + golden: "output/upgrade-without-notes-or-subcharts-with-flag-dry-run-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade` on a chart that has notes but no subcharts should print the upgrade command's + // output with (current chart's) notes. + name: "helm upgrade on chart with notes without subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default", chartWithNotes), + golden: "output/upgrade-with-notes.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run` on a chart that has notes but no subcharts should print the upgrade + // command's dry-run output with (current chart's) notes. Note: The notes in dry-run output include the + // source filename and separator "---". + name: "helm upgrade --dry-run on chart with notes without subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run", chartWithNotes), + golden: "output/upgrade-with-notes-with-flag-dry-run-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --render-subchart-notes` on a chart that has notes but no subcharts should print + // the upgrade command's output with (current chart's) notes, i.e., no subchart's notes as no subchart. + name: "helm upgrade --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --render-subchart-notes", chartWithNotes), + golden: "output/upgrade-with-notes.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run --render-subchart-notes` on a chart that has notes but no subcharts + // should print the upgrade command's dry-run output (current chart's) notes, i.e., no subchart's notes as + // no subchart. Note: The notes in dry-run output include the source filename and separator "---". + name: "helm upgrade --dry-run --render-subchart-notes on chart with notes without subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run --render-subchart-notes", + chartWithNotes), + golden: "output/upgrade-with-notes-with-flag-dry-run-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade` on a chart that has notes and 2 levels of subcharts should print upgrade command's + // output with just root chart's notes, i.e., without subchart's notes. + name: "helm upgrade on chart with notes and subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default", chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/upgrade-with-notes-and-subcharts.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run` on a chart that has notes and 2 levels of subcharts should print the + // upgrade command's dry-run output with just the root chart's notes, i.e., without subcharts' notes. Note: + // The notes in dry-run output include the source filename and separator "---". + name: "helm upgrade --dry-run on chart with notes and subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/upgrade-with-notes-and-subcharts-with-flag-dry-run-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --render-subchart-notes` on a chart that has notes and 2 levels of subcharts should + // print the upgrade command's output with both the root chart and the subcharts' notes. + name: "helm upgrade --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/upgrade-with-notes-and-subcharts-with-flag-render-subchart-notes-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, + { + // Running `helm upgrade --dry-run --render-subchart-notes` on a chart that has notes and 2 levels of + // subcharts should print the upgrade command's dry-run output with both the root chart and the subcharts' + // notes. Note: The notes in dry-run output include the source filename and separator "---". + name: "helm upgrade --dry-run --render-subchart-notes on chart with notes and subcharts", + cmd: fmt.Sprintf("upgrade luffy '%s' --namespace default --dry-run --render-subchart-notes", + chartWithNotesAnd2LevelsOfSubCharts), + golden: "output/" + + "upgrade-with-notes-and-subcharts-with-both-flags-dry-run-and-render-subchart-notes-enabled.txt", + rels: []*release.Release{relMock("luffy", 1, ch)}, + }, } runTestCmd(t, tests) } +// TestUpgradeHelpOutput tests the `helm upgrade --help` command's output text. This is required because the +// --render-subchart-notes flag's description is different for the template command from that of install/upgrade +// commands. +func TestUpgradeHelpOutput(t *testing.T) { + const ( + outputFilePath = "testdata/output/upgrade-help.txt" + testNamespace = "test-namespace" + repositoryCache = "test-repository-cache-dir" + repositoryConfig = "test-repository-config.yaml" + registryConfig = "test-registry-config.json" + contentCache = "test-content-cache" + gnupgHome = "test-gpg" + commandText = "upgrade --help" + ) + + // Reset the envs and the configs at the end of this test so that the updates wouldn’t affect other tests. + defer resetEnv()() + + // Read the expected output file. + expectedOutput, err := os.ReadFile(outputFilePath) + assert.NoError(t, err, "unexpected error while reading expected output's file %q", outputFilePath) + + // Set the configs that might otherwise change based on the local environment if not explicitly set. Note: These + // configs are not related to the current test. + settings.RepositoryCache = repositoryCache + settings.RepositoryConfig = repositoryConfig + settings.RegistryConfig = registryConfig + settings.ContentCache = contentCache + settings.SetNamespace(testNamespace) + t.Setenv("GNUPGHOME", gnupgHome) + + // Run the `helm upgrade --help` command and compare the help text. + _, actualOutput, err := executeActionCommandC(storageFixture(), commandText) + assert.NoError(t, err, "unexpected error running command %q", commandText) + assert.Equal(t, string(expectedOutput), actualOutput, "mismatch of output") +} + func TestUpgradeWithValue(t *testing.T) { releaseName := "funny-bunny-v2" relMock, ch, chartPath := prepareMockRelease(t, releaseName)