Merge branch 'main' into lint-cmd-release-name

pull/12280/head
bartem 1 year ago
commit ae87078dad

@ -39,7 +39,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # pinv3.24.7 uses: github/codeql-action/init@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # pinv3.24.10
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -50,7 +50,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@3ab4101902695724f9365a384f86c1074d94e18c # pinv3.24.7 uses: github/codeql-action/autobuild@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # pinv3.24.10
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@ -64,4 +64,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # pinv3.24.7 uses: github/codeql-action/analyze@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # pinv3.24.10

@ -103,7 +103,7 @@ func newCompletionCmd(out io.Writer) *cobra.Command {
Long: bashCompDesc, Long: bashCompDesc,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
return runCompletionBash(out, cmd) return runCompletionBash(out, cmd)
}, },
} }
@ -115,7 +115,7 @@ func newCompletionCmd(out io.Writer) *cobra.Command {
Long: zshCompDesc, Long: zshCompDesc,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
return runCompletionZsh(out, cmd) return runCompletionZsh(out, cmd)
}, },
} }
@ -127,7 +127,7 @@ func newCompletionCmd(out io.Writer) *cobra.Command {
Long: fishCompDesc, Long: fishCompDesc,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
return runCompletionFish(out, cmd) return runCompletionFish(out, cmd)
}, },
} }
@ -139,7 +139,7 @@ func newCompletionCmd(out io.Writer) *cobra.Command {
Long: powershellCompDesc, Long: powershellCompDesc,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
return runCompletionPowershell(out, cmd) return runCompletionPowershell(out, cmd)
}, },
} }

@ -64,7 +64,7 @@ func newCreateCmd(out io.Writer) *cobra.Command {
Short: "create a new chart with the given name", Short: "create a new chart with the given name",
Long: createDesc, Long: createDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
// Allow file completion when completing the argument for the name // Allow file completion when completing the argument for the name
// which could be a path // which could be a path
@ -73,7 +73,7 @@ func newCreateCmd(out io.Writer) *cobra.Command {
// No more completions, so disable file completion // No more completions, so disable file completion
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.name = args[0] o.name = args[0]
o.starterDir = helmpath.DataPath("starters") o.starterDir = helmpath.DataPath("starters")
return o.run(out) return o.run(out)

@ -106,7 +106,7 @@ func newDependencyListCmd(out io.Writer) *cobra.Command {
Short: "list the dependencies for the given chart", Short: "list the dependencies for the given chart",
Long: dependencyListDesc, Long: dependencyListDesc,
Args: require.MaximumNArgs(1), Args: require.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
chartpath := "." chartpath := "."
if len(args) > 0 { if len(args) > 0 {
chartpath = filepath.Clean(args[0]) chartpath = filepath.Clean(args[0])

@ -49,7 +49,7 @@ func newDependencyBuildCmd(cfg *action.Configuration, out io.Writer) *cobra.Comm
Short: "rebuild the charts/ directory based on the Chart.lock file", Short: "rebuild the charts/ directory based on the Chart.lock file",
Long: dependencyBuildDesc, Long: dependencyBuildDesc,
Args: require.MaximumNArgs(1), Args: require.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
chartpath := "." chartpath := "."
if len(args) > 0 { if len(args) > 0 {
chartpath = filepath.Clean(args[0]) chartpath = filepath.Clean(args[0])

@ -52,7 +52,7 @@ func newDependencyUpdateCmd(cfg *action.Configuration, out io.Writer) *cobra.Com
Short: "update charts/ based on the contents of Chart.yaml", Short: "update charts/ based on the contents of Chart.yaml",
Long: dependencyUpDesc, Long: dependencyUpDesc,
Args: require.MaximumNArgs(1), Args: require.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
chartpath := "." chartpath := "."
if len(args) > 0 { if len(args) > 0 {
chartpath = filepath.Clean(args[0]) chartpath = filepath.Clean(args[0])

@ -59,7 +59,7 @@ func newDocsCmd(out io.Writer) *cobra.Command {
Hidden: true, Hidden: true,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
o.topCmd = cmd.Root() o.topCmd = cmd.Root()
return o.run(out) return o.run(out)
}, },
@ -70,7 +70,7 @@ func newDocsCmd(out io.Writer) *cobra.Command {
f.StringVar(&o.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)") f.StringVar(&o.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)")
f.BoolVar(&o.generateHeaders, "generate-headers", false, "generate standard headers for markdown files") f.BoolVar(&o.generateHeaders, "generate-headers", false, "generate standard headers for markdown files")
cmd.RegisterFlagCompletionFunc("type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { cmd.RegisterFlagCompletionFunc("type", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"bash", "man", "markdown"}, cobra.ShellCompDirectiveNoFileComp return []string{"bash", "man", "markdown"}, cobra.ShellCompDirectiveNoFileComp
}) })

@ -36,7 +36,7 @@ func newEnvCmd(out io.Writer) *cobra.Command {
Short: "helm client environment information", Short: "helm client environment information",
Long: envHelp, Long: envHelp,
Args: require.MaximumNArgs(1), Args: require.MaximumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
keys := getSortedEnvVarKeys() keys := getSortedEnvVarKeys()
return keys, cobra.ShellCompDirectiveNoFileComp return keys, cobra.ShellCompDirectiveNoFileComp
@ -44,7 +44,7 @@ func newEnvCmd(out io.Writer) *cobra.Command {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(_ *cobra.Command, args []string) {
envVars := settings.EnvVars() envVars := settings.EnvVars()
if len(args) == 0 { if len(args) == 0 {

@ -72,7 +72,7 @@ func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) {
cmd.Flags().VarP(newOutputValue(output.Table, varRef), outputFlag, "o", cmd.Flags().VarP(newOutputValue(output.Table, varRef), outputFlag, "o",
fmt.Sprintf("prints the output in the specified format. Allowed values: %s", strings.Join(output.Formats(), ", "))) fmt.Sprintf("prints the output in the specified format. Allowed values: %s", strings.Join(output.Formats(), ", ")))
err := cmd.RegisterFlagCompletionFunc(outputFlag, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc(outputFlag, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
var formatNames []string var formatNames []string
for format, desc := range output.FormatsWithDesc() { for format, desc := range output.FormatsWithDesc() {
formatNames = append(formatNames, fmt.Sprintf("%s\t%s", format, desc)) formatNames = append(formatNames, fmt.Sprintf("%s\t%s", format, desc))

@ -41,13 +41,13 @@ func newGetAllCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "download all information for a named release", Short: "download all information for a named release",
Long: getAllHelp, Long: getAllHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
res, err := client.Run(args[0]) res, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -65,7 +65,7 @@ func newGetAllCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags() f := cmd.Flags()
f.IntVar(&client.Version, "revision", 0, "get the named release with revision") f.IntVar(&client.Version, "revision", 0, "get the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -41,13 +41,13 @@ func newGetHooksCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "download all hooks for a named release", Short: "download all hooks for a named release",
Long: getHooksHelp, Long: getHooksHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
res, err := client.Run(args[0]) res, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -60,7 +60,7 @@ func newGetHooksCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
cmd.Flags().IntVar(&client.Version, "revision", 0, "get the named release with revision") cmd.Flags().IntVar(&client.Version, "revision", 0, "get the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -43,13 +43,13 @@ func newGetManifestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
Short: "download the manifest for a named release", Short: "download the manifest for a named release",
Long: getManifestHelp, Long: getManifestHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
res, err := client.Run(args[0]) res, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -60,7 +60,7 @@ func newGetManifestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
} }
cmd.Flags().IntVar(&client.Version, "revision", 0, "get the named release with revision") cmd.Flags().IntVar(&client.Version, "revision", 0, "get the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -40,13 +40,13 @@ func newGetMetadataCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
Use: "metadata RELEASE_NAME", Use: "metadata RELEASE_NAME",
Short: "This command fetches metadata for a given release", Short: "This command fetches metadata for a given release",
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
releaseMetadata, err := client.Run(args[0]) releaseMetadata, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -57,7 +57,7 @@ func newGetMetadataCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
f := cmd.Flags() f := cmd.Flags()
f.IntVar(&client.Version, "revision", 0, "specify release revision") f.IntVar(&client.Version, "revision", 0, "specify release revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -39,13 +39,13 @@ func newGetNotesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "download the notes for a named release", Short: "download the notes for a named release",
Long: getNotesHelp, Long: getNotesHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
res, err := client.Run(args[0]) res, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -59,7 +59,7 @@ func newGetNotesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags() f := cmd.Flags()
f.IntVar(&client.Version, "revision", 0, "get the named release with revision") f.IntVar(&client.Version, "revision", 0, "get the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -46,13 +46,13 @@ func newGetValuesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "download the values file for a named release", Short: "download the values file for a named release",
Long: getValuesHelp, Long: getValuesHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
vals, err := client.Run(args[0]) vals, err := client.Run(args[0])
if err != nil { if err != nil {
return err return err
@ -63,7 +63,7 @@ func newGetValuesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags() f := cmd.Flags()
f.IntVar(&client.Version, "revision", 0, "get the named release with revision") f.IntVar(&client.Version, "revision", 0, "get the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -94,7 +94,7 @@ func executeActionCommandStdinC(store *storage.Storage, in *os.File, cmd string)
Releases: store, Releases: store,
KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard},
Capabilities: chartutil.DefaultCapabilities, Capabilities: chartutil.DefaultCapabilities,
Log: func(format string, v ...interface{}) {}, Log: func(_ string, _ ...interface{}) {},
} }
root, err := newRootCmd(actionConfig, buf, args) root, err := newRootCmd(actionConfig, buf, args)

@ -60,13 +60,13 @@ func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "fetch release history", Short: "fetch release history",
Aliases: []string{"hist"}, Aliases: []string{"hist"},
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
history, err := getHistory(client, args[0]) history, err := getHistory(client, args[0])
if err != nil { if err != nil {
return err return err

@ -136,7 +136,7 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "install a chart", Short: "install a chart",
Long: installDesc, Long: installDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstall(args, toComplete, client) return compInstall(args, toComplete, client)
}, },
RunE: func(_ *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
@ -202,7 +202,7 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal
addValueOptionsFlags(f, valueOpts) addValueOptionsFlags(f, valueOpts)
addChartPathOptionsFlags(f, &client.ChartPathOptions) addChartPathOptionsFlags(f, &client.ChartPathOptions)
err := cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("version", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
requiredArgs := 2 requiredArgs := 2
if client.GenerateName { if client.GenerateName {
requiredArgs = 1 requiredArgs = 1

@ -33,7 +33,7 @@ func TestInstall(t *testing.T) {
} }
defer srv.Stop() defer srv.Stop()
srv.WithMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { srv.WithMiddleware(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth() username, password, ok := r.BasicAuth()
if !ok || username != "username" || password != "password" { if !ok || username != "username" || password != "password" {
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password) t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)

@ -51,7 +51,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
Use: "lint PATH", Use: "lint PATH",
Short: "examine a chart for possible issues", Short: "examine a chart for possible issues",
Long: longLintHelp, Long: longLintHelp,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
paths := []string{"."} paths := []string{"."}
if len(args) > 0 { if len(args) > 0 {
paths = args paths = args
@ -67,7 +67,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
if client.WithSubcharts { if client.WithSubcharts {
for _, p := range paths { for _, p := range paths {
filepath.Walk(filepath.Join(p, "charts"), func(path string, info os.FileInfo, err error) error { filepath.Walk(filepath.Join(p, "charts"), func(path string, info os.FileInfo, _ error) error {
if info != nil { if info != nil {
if info.Name() == "Chart.yaml" { if info.Name() == "Chart.yaml" {
paths = append(paths, filepath.Dir(path)) paths = append(paths, filepath.Dir(path))

@ -69,7 +69,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
if client.AllNamespaces { if client.AllNamespaces {
if err := cfg.Init(settings.RESTClientGetter(), "", os.Getenv("HELM_DRIVER"), debug); err != nil { if err := cfg.Init(settings.RESTClientGetter(), "", os.Getenv("HELM_DRIVER"), debug); err != nil {
return err return err

@ -301,7 +301,7 @@ func addPluginCommands(plugin *plugin.Plugin, baseCmd *cobra.Command, cmds *plug
// to the dynamic completion script of the plugin. // to the dynamic completion script of the plugin.
DisableFlagParsing: true, DisableFlagParsing: true,
// A Run is required for it to be a valid command without subcommands // A Run is required for it to be a valid command without subcommands
Run: func(cmd *cobra.Command, args []string) {}, Run: func(_ *cobra.Command, _ []string) {},
} }
baseCmd.AddCommand(subCmd) baseCmd.AddCommand(subCmd)
addPluginCommands(plugin, subCmd, &cmd) addPluginCommands(plugin, subCmd, &cmd)

@ -55,7 +55,7 @@ func newPackageCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Use: "package [CHART_PATH] [...]", Use: "package [CHART_PATH] [...]",
Short: "package a chart directory into a chart archive", Short: "package a chart directory into a chart archive",
Long: packageDesc, Long: packageDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {
return errors.Errorf("need at least one argument, the path to the chart") return errors.Errorf("need at least one argument, the path to the chart")
} }

@ -44,7 +44,7 @@ func newPluginInstallCmd(out io.Writer) *cobra.Command {
Long: pluginInstallDesc, Long: pluginInstallDesc,
Aliases: []string{"add"}, Aliases: []string{"add"},
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
// We do file completion, in case the plugin is local // We do file completion, in case the plugin is local
return nil, cobra.ShellCompDirectiveDefault return nil, cobra.ShellCompDirectiveDefault
@ -52,10 +52,10 @@ func newPluginInstallCmd(out io.Writer) *cobra.Command {
// No more completion once the plugin path has been specified // No more completion once the plugin path has been specified
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(_ *cobra.Command, args []string) error {
return o.complete(args) return o.complete(args)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
return o.run(out) return o.run(out)
}, },
} }

@ -31,7 +31,7 @@ func newPluginListCmd(out io.Writer) *cobra.Command {
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Short: "list installed Helm plugins", Short: "list installed Helm plugins",
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
debug("pluginDirs: %s", settings.PluginsDirectory) debug("pluginDirs: %s", settings.PluginsDirectory)
plugins, err := plugin.FindPlugins(settings.PluginsDirectory) plugins, err := plugin.FindPlugins(settings.PluginsDirectory)
if err != nil { if err != nil {

@ -38,13 +38,13 @@ func newPluginUninstallCmd(out io.Writer) *cobra.Command {
Use: "uninstall <plugin>...", Use: "uninstall <plugin>...",
Aliases: []string{"rm", "remove"}, Aliases: []string{"rm", "remove"},
Short: "uninstall one or more Helm plugins", Short: "uninstall one or more Helm plugins",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(_ *cobra.Command, args []string) error {
return o.complete(args) return o.complete(args)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
return o.run(out) return o.run(out)
}, },
} }

@ -39,13 +39,13 @@ func newPluginUpdateCmd(out io.Writer) *cobra.Command {
Use: "update <plugin>...", Use: "update <plugin>...",
Aliases: []string{"up"}, Aliases: []string{"up"},
Short: "update one or more Helm plugins", Short: "update one or more Helm plugins",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp return compListPlugins(toComplete, args), cobra.ShellCompDirectiveNoFileComp
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(_ *cobra.Command, args []string) error {
return o.complete(args) return o.complete(args)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
return o.run(out) return o.run(out)
}, },
} }

@ -51,13 +51,13 @@ func newPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Aliases: []string{"fetch"}, Aliases: []string{"fetch"},
Long: pullDesc, Long: pullDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListCharts(toComplete, false) return compListCharts(toComplete, false)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.Settings = settings client.Settings = settings
if client.Version == "" && client.Devel { if client.Version == "" && client.Devel {
debug("setting version to >0.0.0-0") debug("setting version to >0.0.0-0")
@ -90,7 +90,7 @@ func newPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.StringVarP(&client.DestDir, "destination", "d", ".", "location to write the chart. If this and untardir are specified, untardir is appended to this") f.StringVarP(&client.DestDir, "destination", "d", ".", "location to write the chart. If this and untardir are specified, untardir is appended to this")
addChartPathOptionsFlags(f, &client.ChartPathOptions) addChartPathOptionsFlags(f, &client.ChartPathOptions)
err := cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("version", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 1 { if len(args) != 1 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }

@ -258,7 +258,7 @@ func TestPullWithCredentialsCmd(t *testing.T) {
} }
defer srv.Stop() defer srv.Stop()
srv.WithMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { srv.WithMiddleware(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth() username, password, ok := r.BasicAuth()
if !ok || username != "username" || password != "password" { if !ok || username != "username" || password != "password" {
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password) t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)

@ -50,7 +50,7 @@ func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "push a chart to remote", Short: "push a chart to remote",
Long: pushDesc, Long: pushDesc,
Args: require.MinimumNArgs(2), Args: require.MinimumNArgs(2),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
// Do file completion for the chart file to push // Do file completion for the chart file to push
return nil, cobra.ShellCompDirectiveDefault return nil, cobra.ShellCompDirectiveDefault
@ -67,7 +67,7 @@ func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
registryClient, err := newRegistryClient(o.certFile, o.keyFile, o.caFile, o.insecureSkipTLSverify, o.plainHTTP) registryClient, err := newRegistryClient(o.certFile, o.keyFile, o.caFile, o.insecureSkipTLSverify, o.plainHTTP)
if err != nil { if err != nil {
return fmt.Errorf("missing registry client: %w", err) return fmt.Errorf("missing registry client: %w", err)

@ -54,7 +54,7 @@ func newRegistryLoginCmd(cfg *action.Configuration, out io.Writer) *cobra.Comman
Long: registryLoginDesc, Long: registryLoginDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
hostname := args[0] hostname := args[0]
username, password, err := getUsernamePassword(o.username, o.password, o.passwordFromStdinOpt) username, password, err := getUsernamePassword(o.username, o.password, o.passwordFromStdinOpt)

@ -36,7 +36,7 @@ func newRegistryLogoutCmd(cfg *action.Configuration, out io.Writer) *cobra.Comma
Long: registryLogoutDesc, Long: registryLogoutDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
hostname := args[0] hostname := args[0]
return action.NewRegistryLogout(cfg).Run(out, hostname) return action.NewRegistryLogout(cfg).Run(out, hostname)
}, },

@ -48,13 +48,13 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
Short: "run tests for a release", Short: "run tests for a release",
Long: releaseTestHelp, Long: releaseTestHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.Namespace = settings.Namespace() client.Namespace = settings.Namespace()
notName := regexp.MustCompile(`^!\s?name=`) notName := regexp.MustCompile(`^!\s?name=`)
for _, f := range filter { for _, f := range filter {

@ -72,7 +72,7 @@ func newRepoAddCmd(out io.Writer) *cobra.Command {
Short: "add a chart repository", Short: "add a chart repository",
Args: require.ExactArgs(2), Args: require.ExactArgs(2),
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.name = args[0] o.name = args[0]
o.url = args[1] o.url = args[1]
o.repoFile = settings.RepositoryConfig o.repoFile = settings.RepositoryConfig

@ -54,7 +54,7 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command {
Short: "generate an index file given a directory containing packaged charts", Short: "generate an index file given a directory containing packaged charts",
Long: repoIndexDesc, Long: repoIndexDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
// Allow file completion when completing the argument for the directory // Allow file completion when completing the argument for the directory
return nil, cobra.ShellCompDirectiveDefault return nil, cobra.ShellCompDirectiveDefault
@ -62,7 +62,7 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command {
// No more completions, so disable file completion // No more completions, so disable file completion
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.dir = args[0] o.dir = args[0]
return o.run(out) return o.run(out)
}, },

@ -37,7 +37,7 @@ func newRepoListCmd(out io.Writer) *cobra.Command {
Short: "list chart repositories", Short: "list chart repositories",
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
f, _ := repo.LoadFile(settings.RepositoryConfig) f, _ := repo.LoadFile(settings.RepositoryConfig)
if len(f.Repositories) == 0 && !(outfmt == output.JSON || outfmt == output.YAML) { if len(f.Repositories) == 0 && !(outfmt == output.JSON || outfmt == output.YAML) {
return errors.New("no repositories to show") return errors.New("no repositories to show")

@ -44,10 +44,10 @@ func newRepoRemoveCmd(out io.Writer) *cobra.Command {
Aliases: []string{"rm"}, Aliases: []string{"rm"},
Short: "remove one or more chart repositories", Short: "remove one or more chart repositories",
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.repoFile = settings.RepositoryConfig o.repoFile = settings.RepositoryConfig
o.repoCache = settings.RepositoryCache o.repoCache = settings.RepositoryCache
o.names = args o.names = args

@ -57,10 +57,10 @@ func newRepoUpdateCmd(out io.Writer) *cobra.Command {
Short: "update information of available charts locally from chart repositories", Short: "update information of available charts locally from chart repositories",
Long: updateDesc, Long: updateDesc,
Args: require.MinimumNArgs(0), Args: require.MinimumNArgs(0),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.repoFile = settings.RepositoryConfig o.repoFile = settings.RepositoryConfig
o.repoCache = settings.RepositoryCache o.repoCache = settings.RepositoryCache
o.names = args o.names = args

@ -34,7 +34,7 @@ func TestUpdateCmd(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test. // Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently. // The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer, failOnRepoUpdateFail bool) error { updater := func(repos []*repo.ChartRepository, out io.Writer, _ bool) error {
for _, re := range repos { for _, re := range repos {
fmt.Fprintln(out, re.Config.Name) fmt.Fprintln(out, re.Config.Name)
} }
@ -59,7 +59,7 @@ func TestUpdateCmdMultiple(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test. // Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently. // The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer, failOnRepoUpdateFail bool) error { updater := func(repos []*repo.ChartRepository, out io.Writer, _ bool) error {
for _, re := range repos { for _, re := range repos {
fmt.Fprintln(out, re.Config.Name) fmt.Fprintln(out, re.Config.Name)
} }
@ -85,7 +85,7 @@ func TestUpdateCmdInvalid(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test. // Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently. // The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer, failOnRepoUpdateFail bool) error { updater := func(repos []*repo.ChartRepository, out io.Writer, _ bool) error {
for _, re := range repos { for _, re := range repos {
fmt.Fprintln(out, re.Config.Name) fmt.Fprintln(out, re.Config.Name)
} }

@ -46,7 +46,7 @@ func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "roll back a release to a previous revision", Short: "roll back a release to a previous revision",
Long: rollbackDesc, Long: rollbackDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
} }
@ -57,7 +57,7 @@ func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
if len(args) > 1 { if len(args) > 1 {
ver, err := strconv.Atoi(args[1]) ver, err := strconv.Atoi(args[1])
if err != nil { if err != nil {

@ -100,7 +100,7 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
addKlogFlags(flags) addKlogFlags(flags)
// Setup shell completion for the namespace flag // Setup shell completion for the namespace flag
err := cmd.RegisterFlagCompletionFunc("namespace", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("namespace", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
if client, err := actionConfig.KubernetesClientSet(); err == nil { if client, err := actionConfig.KubernetesClientSet(); err == nil {
// Choose a long enough timeout that the user notices something is not working // Choose a long enough timeout that the user notices something is not working
// but short enough that the user is not made to wait very long // but short enough that the user is not made to wait very long
@ -123,7 +123,7 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
} }
// Setup shell completion for the kube-context flag // Setup shell completion for the kube-context flag
err = cmd.RegisterFlagCompletionFunc("kube-context", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err = cmd.RegisterFlagCompletionFunc("kube-context", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
cobra.CompDebugln("About to get the different kube-contexts", settings.Debug) cobra.CompDebugln("About to get the different kube-contexts", settings.Debug)
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()

@ -64,7 +64,7 @@ func newSearchHubCmd(out io.Writer) *cobra.Command {
Use: "hub [KEYWORD]", Use: "hub [KEYWORD]",
Short: "search for charts in the Artifact Hub or your own hub instance", Short: "search for charts in the Artifact Hub or your own hub instance",
Long: searchHubDesc, Long: searchHubDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
return o.run(out, args) return o.run(out, args)
}, },
} }

@ -27,7 +27,7 @@ func TestSearchHubCmd(t *testing.T) {
// Setup a mock search service // Setup a mock search service
var searchResult = `{"data":[{"id":"stable/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"stable","url":"https://charts.helm.sh/stable"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/stable/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T17:57:31.38Z","digest":"119c499251bffd4b06ff0cd5ac98c2ce32231f84899fb4825be6c2d90971c742","urls":["https://charts.helm.sh/stable/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/stable/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/stable/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/stable/phpmyadmin/versions/3.0.0"}}}},{"id":"bitnami/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"bitnami","url":"https://charts.bitnami.com"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/bitnami/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T18:34:13.341Z","digest":"66d77cf6d8c2b52c488d0a294cd4996bd5bad8dc41d3829c394498fb401c008a","urls":["https://charts.bitnami.com/bitnami/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/bitnami/phpmyadmin/versions/3.0.0"}}}}]}` var searchResult = `{"data":[{"id":"stable/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"stable","url":"https://charts.helm.sh/stable"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/stable/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T17:57:31.38Z","digest":"119c499251bffd4b06ff0cd5ac98c2ce32231f84899fb4825be6c2d90971c742","urls":["https://charts.helm.sh/stable/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/stable/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/stable/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/stable/phpmyadmin/versions/3.0.0"}}}},{"id":"bitnami/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"bitnami","url":"https://charts.bitnami.com"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/bitnami/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T18:34:13.341Z","digest":"66d77cf6d8c2b52c488d0a294cd4996bd5bad8dc41d3829c394498fb401c008a","urls":["https://charts.bitnami.com/bitnami/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/bitnami/phpmyadmin/versions/3.0.0"}}}}]}`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintln(w, searchResult) fmt.Fprintln(w, searchResult)
})) }))
defer ts.Close() defer ts.Close()
@ -57,7 +57,7 @@ func TestSearchHubListRepoCmd(t *testing.T) {
// Setup a mock search service // Setup a mock search service
var searchResult = `{"data":[{"id":"stable/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"stable","url":"https://charts.helm.sh/stable"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/stable/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T17:57:31.38Z","digest":"119c499251bffd4b06ff0cd5ac98c2ce32231f84899fb4825be6c2d90971c742","urls":["https://charts.helm.sh/stable/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/stable/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/stable/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/stable/phpmyadmin/versions/3.0.0"}}}},{"id":"bitnami/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"bitnami","url":"https://charts.bitnami.com"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/bitnami/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T18:34:13.341Z","digest":"66d77cf6d8c2b52c488d0a294cd4996bd5bad8dc41d3829c394498fb401c008a","urls":["https://charts.bitnami.com/bitnami/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/bitnami/phpmyadmin/versions/3.0.0"}}}}]}` var searchResult = `{"data":[{"id":"stable/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"stable","url":"https://charts.helm.sh/stable"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/stable/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T17:57:31.38Z","digest":"119c499251bffd4b06ff0cd5ac98c2ce32231f84899fb4825be6c2d90971c742","urls":["https://charts.helm.sh/stable/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/stable/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/stable/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/stable/phpmyadmin/versions/3.0.0"}}}},{"id":"bitnami/phpmyadmin","type":"chart","attributes":{"name":"phpmyadmin","repo":{"name":"bitnami","url":"https://charts.bitnami.com"},"description":"phpMyAdmin is an mysql administration frontend","home":"https://www.phpmyadmin.net/","keywords":["mariadb","mysql","phpmyadmin"],"maintainers":[{"name":"Bitnami","email":"containers@bitnami.com"}],"sources":["https://github.com/bitnami/bitnami-docker-phpmyadmin"],"icon":""},"links":{"self":"/v1/charts/bitnami/phpmyadmin"},"relationships":{"latestChartVersion":{"data":{"version":"3.0.0","app_version":"4.9.0-1","created":"2019-08-08T18:34:13.341Z","digest":"66d77cf6d8c2b52c488d0a294cd4996bd5bad8dc41d3829c394498fb401c008a","urls":["https://charts.bitnami.com/bitnami/phpmyadmin-3.0.0.tgz"],"readme":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/README.md","values":"/v1/assets/bitnami/phpmyadmin/versions/3.0.0/values.yaml"},"links":{"self":"/v1/charts/bitnami/phpmyadmin/versions/3.0.0"}}}}]}`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintln(w, searchResult) fmt.Fprintln(w, searchResult)
})) }))
defer ts.Close() defer ts.Close()
@ -155,7 +155,7 @@ func TestSearchHubCmd_FailOnNoResponseTests(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Setup a mock search service // Setup a mock search service
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintln(w, tt.response) fmt.Fprintln(w, tt.response)
})) }))
defer ts.Close() defer ts.Close()

@ -81,7 +81,7 @@ func newSearchRepoCmd(out io.Writer) *cobra.Command {
Use: "repo [keyword]", Use: "repo [keyword]",
Short: "search repositories for a keyword in charts", Short: "search repositories for a keyword in charts",
Long: searchRepoDesc, Long: searchRepoDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
o.repoFile = settings.RepositoryConfig o.repoFile = settings.RepositoryConfig
o.repoCacheDir = settings.RepositoryCache o.repoCacheDir = settings.RepositoryCache
return o.run(out, args) return o.run(out, args)

@ -69,7 +69,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
// Function providing dynamic auto-completion // Function providing dynamic auto-completion
validArgsFunc := func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { validArgsFunc := func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
@ -82,7 +82,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: showAllDesc, Long: showAllDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: validArgsFunc, ValidArgsFunction: validArgsFunc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.OutputFormat = action.ShowAll client.OutputFormat = action.ShowAll
err := addRegistryClient(client) err := addRegistryClient(client)
if err != nil { if err != nil {
@ -103,7 +103,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: showValuesDesc, Long: showValuesDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: validArgsFunc, ValidArgsFunction: validArgsFunc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.OutputFormat = action.ShowValues client.OutputFormat = action.ShowValues
err := addRegistryClient(client) err := addRegistryClient(client)
if err != nil { if err != nil {
@ -124,7 +124,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: showChartDesc, Long: showChartDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: validArgsFunc, ValidArgsFunction: validArgsFunc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.OutputFormat = action.ShowChart client.OutputFormat = action.ShowChart
err := addRegistryClient(client) err := addRegistryClient(client)
if err != nil { if err != nil {
@ -145,7 +145,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: readmeChartDesc, Long: readmeChartDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: validArgsFunc, ValidArgsFunction: validArgsFunc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.OutputFormat = action.ShowReadme client.OutputFormat = action.ShowReadme
err := addRegistryClient(client) err := addRegistryClient(client)
if err != nil { if err != nil {
@ -166,7 +166,7 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Long: showCRDsDesc, Long: showCRDsDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: validArgsFunc, ValidArgsFunction: validArgsFunc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.OutputFormat = action.ShowCRDs client.OutputFormat = action.ShowCRDs
err := addRegistryClient(client) err := addRegistryClient(client)
if err != nil { if err != nil {
@ -199,7 +199,7 @@ func addShowFlags(subCmd *cobra.Command, client *action.Show) {
} }
addChartPathOptionsFlags(f, &client.ChartPathOptions) addChartPathOptionsFlags(f, &client.ChartPathOptions)
err := subCmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := subCmd.RegisterFlagCompletionFunc("version", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 1 { if len(args) != 1 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }

@ -58,13 +58,13 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "display the status of the named release", Short: "display the status of the named release",
Long: statusHelp, Long: statusHelp,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 { if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
// When the output format is a table the resources should be fetched // When the output format is a table the resources should be fetched
// and displayed as a table. When YAML or JSON the resources will be // and displayed as a table. When YAML or JSON the resources will be
@ -88,7 +88,7 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.IntVar(&client.Version, "revision", 0, "if set, display the status of the named release with revision") f.IntVar(&client.Version, "revision", 0, "if set, display the status of the named release with revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("revision", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 { if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0]) return compListRevisions(toComplete, cfg, args[0])
} }

@ -61,7 +61,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "locally render templates", Short: "locally render templates",
Long: templateDesc, Long: templateDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstall(args, toComplete, client) return compInstall(args, toComplete, client)
}, },
RunE: func(_ *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {

@ -0,0 +1,7 @@
Release "funny-bunny" does not exist. Installing it now.
NAME: funny-bunny
LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default
STATUS: deployed
REVISION: 3
TEST SUITE: None

@ -47,10 +47,10 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "uninstall a release", Short: "uninstall a release",
Long: uninstallDesc, Long: uninstallDesc,
Args: require.MinimumNArgs(1), Args: require.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
validationErr := validateCascadeFlag(client) validationErr := validateCascadeFlag(client)
if validationErr != nil { if validationErr != nil {
return validationErr return validationErr

@ -36,6 +36,7 @@ import (
"helm.sh/helm/v3/pkg/cli/values" "helm.sh/helm/v3/pkg/cli/values"
"helm.sh/helm/v3/pkg/downloader" "helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/storage/driver" "helm.sh/helm/v3/pkg/storage/driver"
) )
@ -89,7 +90,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
Short: "upgrade a release", Short: "upgrade a release",
Long: upgradeDesc, Long: upgradeDesc,
Args: require.ExactArgs(2), Args: require.ExactArgs(2),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
return compListReleases(toComplete, args, cfg) return compListReleases(toComplete, args, cfg)
} }
@ -98,7 +99,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
client.Namespace = settings.Namespace() client.Namespace = settings.Namespace()
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile, registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
@ -115,12 +116,13 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client.DryRunOption = "none" client.DryRunOption = "none"
} }
// Fixes #7002 - Support reading values from STDIN for `upgrade` command // Fixes #7002 - Support reading values from STDIN for `upgrade` command
// Must load values AFTER determining if we have to call install so that values loaded from stdin are are not read twice // Must load values AFTER determining if we have to call install so that values loaded from stdin are not read twice
if client.Install { if client.Install {
// If a release does not exist, install it. // If a release does not exist, install it.
histClient := action.NewHistory(cfg) histClient := action.NewHistory(cfg)
histClient.Max = 1 histClient.Max = 1
if _, err := histClient.Run(args[0]); err == driver.ErrReleaseNotFound { versions, err := histClient.Run(args[0])
if err == driver.ErrReleaseNotFound || isReleaseUninstalled(versions) {
// Only print this to stdout for table output // Only print this to stdout for table output
if outfmt == output.Table { if outfmt == output.Table {
fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", args[0]) fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", args[0])
@ -148,6 +150,10 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
instClient.EnableDNS = client.EnableDNS instClient.EnableDNS = client.EnableDNS
instClient.HideSecret = client.HideSecret instClient.HideSecret = client.HideSecret
if isReleaseUninstalled(versions) {
instClient.Replace = true
}
rel, err := runInstall(args, instClient, valueOpts, out) rel, err := runInstall(args, instClient, valueOpts, out)
if err != nil { if err != nil {
return err return err
@ -274,7 +280,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
bindOutputFlag(cmd, &outfmt) bindOutputFlag(cmd, &outfmt)
bindPostRenderFlag(cmd, &client.PostRenderer) bindPostRenderFlag(cmd, &client.PostRenderer)
err := cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { err := cmd.RegisterFlagCompletionFunc("version", func(_ *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 2 { if len(args) != 2 {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
} }
@ -287,3 +293,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return cmd return cmd
} }
func isReleaseUninstalled(versions []*release.Release) bool {
return len(versions) > 0 && versions[len(versions)-1].Info.Status == release.StatusUninstalled
}

@ -175,6 +175,12 @@ func TestUpgradeCmd(t *testing.T) {
wantError: true, wantError: true,
rels: []*release.Release{relWithStatusMock("funny-bunny", 2, ch, release.StatusPendingInstall)}, rels: []*release.Release{relWithStatusMock("funny-bunny", 2, ch, release.StatusPendingInstall)},
}, },
{
name: "install a previously uninstalled release with '--keep-history' using 'upgrade --install'",
cmd: fmt.Sprintf("upgrade funny-bunny -i '%s'", chartPath),
golden: "output/upgrade-uninstalled-with-keep-history.txt",
rels: []*release.Release{relWithStatusMock("funny-bunny", 2, ch, release.StatusUninstalled)},
},
} }
runTestCmd(t, tests) runTestCmd(t, tests)
} }

@ -44,7 +44,7 @@ func newVerifyCmd(out io.Writer) *cobra.Command {
Short: "verify that a chart at the given path has been signed and is valid", Short: "verify that a chart at the given path has been signed and is valid",
Long: verifyDesc, Long: verifyDesc,
Args: require.ExactArgs(1), Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 { if len(args) == 0 {
// Allow file completion when completing the argument for the path // Allow file completion when completing the argument for the path
return nil, cobra.ShellCompDirectiveDefault return nil, cobra.ShellCompDirectiveDefault
@ -52,7 +52,7 @@ func newVerifyCmd(out io.Writer) *cobra.Command {
// No more completions, so disable file completion // No more completions, so disable file completion
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
err := client.Run(args[0]) err := client.Run(args[0])
if err != nil { if err != nil {
return err return err

@ -66,7 +66,7 @@ func newVersionCmd(out io.Writer) *cobra.Command {
Long: versionDesc, Long: versionDesc,
Args: require.NoArgs, Args: require.NoArgs,
ValidArgsFunction: noCompletions, ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
return o.run(out) return o.run(out)
}, },
} }

@ -34,7 +34,7 @@ require (
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/xeipuuv/gojsonschema v1.2.0 github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/crypto v0.17.0 golang.org/x/crypto v0.17.0
golang.org/x/term v0.15.0 golang.org/x/term v0.18.0
golang.org/x/text v0.14.0 golang.org/x/text v0.14.0
k8s.io/api v0.29.0 k8s.io/api v0.29.0
k8s.io/apiextensions-apiserver v0.29.0 k8s.io/apiextensions-apiserver v0.29.0
@ -67,7 +67,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v24.0.6+incompatible // indirect github.com/docker/cli v24.0.6+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect github.com/docker/docker v24.0.9+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
@ -150,12 +150,12 @@ require (
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.18.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.58.3 // indirect google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

@ -80,8 +80,8 @@ github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWT
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -483,14 +483,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -540,8 +540,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

@ -28,7 +28,7 @@ var searchResult = `{"data":[{"id":"stable/phpmyadmin","type":"chart","attribute
func TestSearch(t *testing.T) { func TestSearch(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintln(w, searchResult) fmt.Fprintln(w, searchResult)
})) }))
defer ts.Close() defer ts.Close()

@ -119,7 +119,7 @@ func mark(info os.FileInfo, err error, errors *[]error, clear bool) error {
return err return err
} }
name := info.Name() name := info.Name()
walkTree(tree, tree.name, func(path string, n *Node) { walkTree(tree, tree.name, func(_ string, n *Node) {
if n.name == name { if n.name == name {
n.marks++ n.marks++
} }
@ -131,7 +131,7 @@ func TestWalk(t *testing.T) {
makeTree(t) makeTree(t)
errors := make([]error, 0, 10) errors := make([]error, 0, 10)
clear := true clear := true
markFn := func(path string, info os.FileInfo, err error) error { markFn := func(_ string, info os.FileInfo, err error) error {
return mark(info, err, &errors, clear) return mark(info, err, &errors, clear)
} }
// Expect no errors. // Expect no errors.

@ -161,7 +161,7 @@ func passphraseFileFetcher(passphraseFile string, stdin *os.File) (provenance.Pa
if err != nil { if err != nil {
return nil, err return nil, err
} }
return func(name string) ([]byte, error) { return func(_ string) ([]byte, error) {
return passphrase, nil return passphrase, nil
}, nil }, nil
} }

@ -31,8 +31,8 @@ func TestLoadArchiveFiles(t *testing.T) {
}{ }{
{ {
name: "empty input should return no files", name: "empty input should return no files",
generate: func(w *tar.Writer) {}, generate: func(_ *tar.Writer) {},
check: func(t *testing.T, files []*BufferedFile, err error) { check: func(t *testing.T, _ []*BufferedFile, err error) {
if err.Error() != "no files in chart archive" { if err.Error() != "no files in chart archive" {
t.Fatalf(`expected "no files in chart archive", got [%#v]`, err) t.Fatalf(`expected "no files in chart archive", got [%#v]`, err)
} }

@ -44,7 +44,7 @@ const defaultMaxHistory = 10
// defaultBurstLimit sets the default client-side throttling limit // defaultBurstLimit sets the default client-side throttling limit
const defaultBurstLimit = 100 const defaultBurstLimit = 100
// defaultQPS sets the default QPS value to 0 to to use library defaults unless specified // defaultQPS sets the default QPS value to 0 to use library defaults unless specified
const defaultQPS = float32(0) const defaultQPS = float32(0)
// EnvSettings describes all of the environment settings. // EnvSettings describes all of the environment settings.

@ -239,7 +239,7 @@ func (e Engine) initFunMap(t *template.Template) {
// When DNS lookups are not enabled override the sprig function and return // When DNS lookups are not enabled override the sprig function and return
// an empty string. // an empty string.
if !e.EnableDNS { if !e.EnableDNS {
funcMap["getHostByName"] = func(name string) string { funcMap["getHostByName"] = func(_ string) string {
return "" return ""
} }
} }

@ -287,7 +287,7 @@ func TestDownloadTLS(t *testing.T) {
ca, pub, priv := filepath.Join(cd, "rootca.crt"), filepath.Join(cd, "crt.pem"), filepath.Join(cd, "key.pem") ca, pub, priv := filepath.Join(cd, "rootca.crt"), filepath.Join(cd, "crt.pem"), filepath.Join(cd, "key.pem")
insecureSkipTLSverify := false insecureSkipTLSverify := false
tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}))
tlsConf, err := tlsutil.NewClientTLS(pub, priv, ca, insecureSkipTLSverify) tlsConf, err := tlsutil.NewClientTLS(pub, priv, ca, insecureSkipTLSverify)
if err != nil { if err != nil {
t.Fatal(errors.Wrap(err, "can't create TLS config for client")) t.Fatal(errors.Wrap(err, "can't create TLS config for client"))
@ -332,7 +332,7 @@ func TestDownloadTLS(t *testing.T) {
} }
func TestDownloadInsecureSkipTLSVerify(t *testing.T) { func TestDownloadInsecureSkipTLSVerify(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) ts := httptest.NewTLSServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}))
defer ts.Close() defer ts.Close()
u, _ := url.ParseRequestURI(ts.URL) u, _ := url.ParseRequestURI(ts.URL)
@ -364,7 +364,7 @@ func TestDownloadInsecureSkipTLSVerify(t *testing.T) {
} }
func TestHTTPGetterTarDownload(t *testing.T) { func TestHTTPGetterTarDownload(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
f, _ := os.Open("testdata/empty-0.0.1.tgz") f, _ := os.Open("testdata/empty-0.0.1.tgz")
defer f.Close() defer f.Close()

@ -173,7 +173,7 @@ func (r *Rules) parseRule(rule string) error {
if strings.HasPrefix(rule, "/") { if strings.HasPrefix(rule, "/") {
// Require path matches the root path. // Require path matches the root path.
p.match = func(n string, fi os.FileInfo) bool { p.match = func(n string, _ os.FileInfo) bool {
rule = strings.TrimPrefix(rule, "/") rule = strings.TrimPrefix(rule, "/")
ok, err := filepath.Match(rule, n) ok, err := filepath.Match(rule, n)
if err != nil { if err != nil {
@ -184,7 +184,7 @@ func (r *Rules) parseRule(rule string) error {
} }
} else if strings.Contains(rule, "/") { } else if strings.Contains(rule, "/") {
// require structural match. // require structural match.
p.match = func(n string, fi os.FileInfo) bool { p.match = func(n string, _ os.FileInfo) bool {
ok, err := filepath.Match(rule, n) ok, err := filepath.Match(rule, n)
if err != nil { if err != nil {
log.Printf("Failed to compile %q: %s", rule, err) log.Printf("Failed to compile %q: %s", rule, err)
@ -193,7 +193,7 @@ func (r *Rules) parseRule(rule string) error {
return ok return ok
} }
} else { } else {
p.match = func(n string, fi os.FileInfo) bool { p.match = func(n string, _ os.FileInfo) bool {
// When there is no slash in the pattern, we evaluate ONLY the // When there is no slash in the pattern, we evaluate ONLY the
// filename. // filename.
n = filepath.Base(n) n = filepath.Base(n)

@ -106,7 +106,7 @@ func (w *waiter) waitForDeletedResources(deleted ResourceList) error {
ctx, cancel := context.WithTimeout(context.Background(), w.timeout) ctx, cancel := context.WithTimeout(context.Background(), w.timeout)
defer cancel() defer cancel()
return wait.PollUntilContextCancel(ctx, 2*time.Second, true, func(ctx context.Context) (bool, error) { return wait.PollUntilContextCancel(ctx, 2*time.Second, true, func(_ context.Context) (bool, error) {
for _, v := range deleted { for _, v := range deleted {
err := v.Get() err := v.Get()
if err == nil || !apierrors.IsNotFound(err) { if err == nil || !apierrors.IsNotFound(err) {

@ -283,10 +283,10 @@ func validateMetadataNameFunc(obj *K8sYamlStruct) validation.ValidateNameFunc {
case "certificatesigningrequest": case "certificatesigningrequest":
// No validation. // No validation.
// https://github.com/kubernetes/kubernetes/blob/v1.20.0/pkg/apis/certificates/validation/validation.go#L137-L140 // https://github.com/kubernetes/kubernetes/blob/v1.20.0/pkg/apis/certificates/validation/validation.go#L137-L140
return func(name string, prefix bool) []string { return nil } return func(_ string, _ bool) []string { return nil }
case "role", "clusterrole", "rolebinding", "clusterrolebinding": case "role", "clusterrole", "rolebinding", "clusterrolebinding":
// https://github.com/kubernetes/kubernetes/blob/v1.20.0/pkg/apis/rbac/validation/validation.go#L32-L34 // https://github.com/kubernetes/kubernetes/blob/v1.20.0/pkg/apis/rbac/validation/validation.go#L32-L34
return func(name string, prefix bool) []string { return func(name string, _ bool) []string {
return apipath.IsValidPathSegmentName(name) return apipath.IsValidPathSegmentName(name)
} }
default: default:

@ -196,7 +196,7 @@ func TestDecryptKey(t *testing.T) {
} }
// We give this a simple callback that returns the password. // We give this a simple callback that returns the password.
if err := k.DecryptKey(func(s string) ([]byte, error) { if err := k.DecryptKey(func(_ string) ([]byte, error) {
return []byte("secret"), nil return []byte("secret"), nil
}); err != nil { }); err != nil {
t.Fatal(err) t.Fatal(err)
@ -208,7 +208,7 @@ func TestDecryptKey(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// Now we give it a bogus password. // Now we give it a bogus password.
if err := k.DecryptKey(func(s string) ([]byte, error) { if err := k.DecryptKey(func(_ string) ([]byte, error) {
return []byte("secrets_and_lies"), nil return []byte("secrets_and_lies"), nil
}); err == nil { }); err == nil {
t.Fatal("Expected an error when giving a bogus passphrase") t.Fatal("Expected an error when giving a bogus passphrase")

@ -29,6 +29,7 @@ import (
"helm.sh/helm/v3/internal/tlsutil" "helm.sh/helm/v3/internal/tlsutil"
"helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/registry" "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/time/ctime"
) )
// OCIPusher is the default OCI backend handler // OCIPusher is the default OCI backend handler
@ -89,6 +90,9 @@ func (pusher *OCIPusher) push(chartRef, href string) error {
path.Join(strings.TrimPrefix(href, fmt.Sprintf("%s://", registry.OCIScheme)), meta.Metadata.Name), path.Join(strings.TrimPrefix(href, fmt.Sprintf("%s://", registry.OCIScheme)), meta.Metadata.Name),
meta.Metadata.Version) meta.Metadata.Version)
chartCreationTime := ctime.Created(stat)
pushOpts = append(pushOpts, registry.PushOptCreationTime(chartCreationTime.Format(time.RFC3339)))
_, err = client.Push(chartBytes, ref, pushOpts...) _, err = client.Push(chartBytes, ref, pushOpts...)
return err return err
} }

@ -124,7 +124,7 @@ func NewClient(options ...ClientOption) (*Client, error) {
"User-Agent": {version.GetUserAgent()}, "User-Agent": {version.GetUserAgent()},
}, },
Cache: cache, Cache: cache,
Credential: func(ctx context.Context, reg string) (registryauth.Credential, error) { Credential: func(_ context.Context, reg string) (registryauth.Credential, error) {
dockerClient, ok := client.authorizer.(*dockerauth.Client) dockerClient, ok := client.authorizer.(*dockerauth.Client)
if !ok { if !ok {
return registryauth.EmptyCredential, errors.New("unable to obtain docker client") return registryauth.EmptyCredential, errors.New("unable to obtain docker client")
@ -198,7 +198,7 @@ func ClientOptPlainHTTP() ClientOption {
// ClientOptResolver returns a function that sets the resolver setting on a client options set // ClientOptResolver returns a function that sets the resolver setting on a client options set
func ClientOptResolver(resolver remotes.Resolver) ClientOption { func ClientOptResolver(resolver remotes.Resolver) ClientOption {
return func(client *Client) { return func(client *Client) {
client.resolver = func(ref registry.Reference) (remotes.Resolver, error) { client.resolver = func(_ registry.Reference) (remotes.Resolver, error) {
return resolver, nil return resolver, nil
} }
} }
@ -527,9 +527,9 @@ type (
} }
pushOperation struct { pushOperation struct {
provData []byte provData []byte
strictMode bool strictMode bool
test bool creationTime string
} }
) )
@ -583,7 +583,7 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
descriptors = append(descriptors, provDescriptor) descriptors = append(descriptors, provDescriptor)
} }
ociAnnotations := generateOCIAnnotations(meta, operation.test) ociAnnotations := generateOCIAnnotations(meta, operation.creationTime)
manifestData, manifest, err := content.GenerateManifest(&configDescriptor, ociAnnotations, descriptors...) manifestData, manifest, err := content.GenerateManifest(&configDescriptor, ociAnnotations, descriptors...)
if err != nil { if err != nil {
@ -652,10 +652,10 @@ func PushOptStrictMode(strictMode bool) PushOption {
} }
} }
// PushOptTest returns a function that sets whether test setting on push // PushOptCreationDate returns a function that sets the creation time
func PushOptTest(test bool) PushOption { func PushOptCreationTime(creationTime string) PushOption {
return func(operation *pushOperation) { return func(operation *pushOperation) {
operation.test = test operation.creationTime = creationTime
} }
} }

@ -166,10 +166,10 @@ func NewRegistryClientWithTLS(out io.Writer, certFile, keyFile, caFile string, i
} }
// generateOCIAnnotations will generate OCI annotations to include within the OCI manifest // generateOCIAnnotations will generate OCI annotations to include within the OCI manifest
func generateOCIAnnotations(meta *chart.Metadata, test bool) map[string]string { func generateOCIAnnotations(meta *chart.Metadata, creationTime string) map[string]string {
// Get annotations from Chart attributes // Get annotations from Chart attributes
ociAnnotations := generateChartOCIAnnotations(meta, test) ociAnnotations := generateChartOCIAnnotations(meta, creationTime)
// Copy Chart annotations // Copy Chart annotations
annotations: annotations:
@ -190,7 +190,7 @@ annotations:
} }
// getChartOCIAnnotations will generate OCI annotations from the provided chart // getChartOCIAnnotations will generate OCI annotations from the provided chart
func generateChartOCIAnnotations(meta *chart.Metadata, test bool) map[string]string { func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[string]string {
chartOCIAnnotations := map[string]string{} chartOCIAnnotations := map[string]string{}
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationDescription, meta.Description) chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationDescription, meta.Description)
@ -198,10 +198,12 @@ func generateChartOCIAnnotations(meta *chart.Metadata, test bool) map[string]str
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationVersion, meta.Version) chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationVersion, meta.Version)
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationURL, meta.Home) chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationURL, meta.Home)
if !test { if len(creationTime) == 0 {
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationCreated, helmtime.Now().UTC().Format(time.RFC3339)) creationTime = helmtime.Now().UTC().Format(time.RFC3339)
} }
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationCreated, creationTime)
if len(meta.Sources) > 0 { if len(meta.Sources) > 0 {
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationSource, meta.Sources[0]) chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationSource, meta.Sources[0])
} }

@ -29,6 +29,8 @@ import (
func TestGenerateOCIChartAnnotations(t *testing.T) { func TestGenerateOCIChartAnnotations(t *testing.T) {
nowString := helmtime.Now().Format(time.RFC3339)
tests := []struct { tests := []struct {
name string name string
chart *chart.Metadata chart *chart.Metadata
@ -43,6 +45,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
}, },
}, },
{ {
@ -56,6 +59,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.url": "https://helm.sh", "org.opencontainers.image.url": "https://helm.sh",
}, },
@ -76,6 +80,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.url": "https://helm.sh", "org.opencontainers.image.url": "https://helm.sh",
"org.opencontainers.image.authors": "John Snow", "org.opencontainers.image.authors": "John Snow",
@ -95,6 +100,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.url": "https://helm.sh", "org.opencontainers.image.url": "https://helm.sh",
"org.opencontainers.image.authors": "John Snow (john@winterfell.com)", "org.opencontainers.image.authors": "John Snow (john@winterfell.com)",
@ -115,6 +121,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.url": "https://helm.sh", "org.opencontainers.image.url": "https://helm.sh",
"org.opencontainers.image.authors": "John Snow (john@winterfell.com), Jane Snow", "org.opencontainers.image.authors": "John Snow (john@winterfell.com), Jane Snow",
@ -133,6 +140,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.source": "https://github.com/helm/helm", "org.opencontainers.image.source": "https://github.com/helm/helm",
}, },
@ -141,7 +149,7 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
result := generateChartOCIAnnotations(tt.chart, true) result := generateChartOCIAnnotations(tt.chart, nowString)
if !reflect.DeepEqual(tt.expect, result) { if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result) t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
@ -152,6 +160,8 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
func TestGenerateOCIAnnotations(t *testing.T) { func TestGenerateOCIAnnotations(t *testing.T) {
nowString := helmtime.Now().Format(time.RFC3339)
tests := []struct { tests := []struct {
name string name string
chart *chart.Metadata chart *chart.Metadata
@ -166,6 +176,7 @@ func TestGenerateOCIAnnotations(t *testing.T) {
map[string]string{ map[string]string{
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.created": nowString,
}, },
}, },
{ {
@ -183,6 +194,7 @@ func TestGenerateOCIAnnotations(t *testing.T) {
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.created": nowString,
"extrakey": "extravlue", "extrakey": "extravlue",
"anotherkey": "anothervalue", "anotherkey": "anothervalue",
}, },
@ -203,6 +215,7 @@ func TestGenerateOCIAnnotations(t *testing.T) {
"org.opencontainers.image.title": "oci", "org.opencontainers.image.title": "oci",
"org.opencontainers.image.version": "0.0.1", "org.opencontainers.image.version": "0.0.1",
"org.opencontainers.image.description": "OCI Helm Chart", "org.opencontainers.image.description": "OCI Helm Chart",
"org.opencontainers.image.created": nowString,
"extrakey": "extravlue", "extrakey": "extravlue",
}, },
}, },
@ -210,7 +223,7 @@ func TestGenerateOCIAnnotations(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
result := generateOCIAnnotations(tt.chart, true) result := generateOCIAnnotations(tt.chart, nowString)
if !reflect.DeepEqual(tt.expect, result) { if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result) t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
@ -220,12 +233,16 @@ func TestGenerateOCIAnnotations(t *testing.T) {
} }
func TestGenerateOCICreatedAnnotations(t *testing.T) { func TestGenerateOCICreatedAnnotations(t *testing.T) {
nowTime := helmtime.Now()
nowTimeString := nowTime.Format(time.RFC3339)
chart := &chart.Metadata{ chart := &chart.Metadata{
Name: "oci", Name: "oci",
Version: "0.0.1", Version: "0.0.1",
} }
result := generateOCIAnnotations(chart, false) result := generateOCIAnnotations(chart, nowTimeString)
// Check that created annotation exists // Check that created annotation exists
if _, ok := result[ocispec.AnnotationCreated]; !ok { if _, ok := result[ocispec.AnnotationCreated]; !ok {
@ -237,4 +254,22 @@ func TestGenerateOCICreatedAnnotations(t *testing.T) {
t.Errorf("%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated]) t.Errorf("%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated])
} }
// Verify default creation time set
result = generateOCIAnnotations(chart, "")
// Check that created annotation exists
if _, ok := result[ocispec.AnnotationCreated]; !ok {
t.Errorf("%s annotation not created", ocispec.AnnotationCreated)
}
if createdTimeAnnotation, err := helmtime.Parse(time.RFC3339, result[ocispec.AnnotationCreated]); err != nil {
t.Errorf("%s annotation with value '%s' not in RFC3339 format", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated])
// Verify creation annotation after time test began
if !nowTime.Before(createdTimeAnnotation) {
t.Errorf("%s annotation with value '%s' not configured properly. Annotation value is not after %s", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated], nowTimeString)
}
}
} }

@ -216,9 +216,12 @@ func initCompromisedRegistryTestServer() string {
} }
func testPush(suite *TestSuite) { func testPush(suite *TestSuite) {
testingChartCreationTime := "1977-09-02T22:04:05Z"
// Bad bytes // Bad bytes
ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost) ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)
_, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptTest(true)) _, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-chart bytes") suite.NotNil(err, "error pushing non-chart bytes")
// Load a test chart // Load a test chart
@ -229,20 +232,20 @@ func testPush(suite *TestSuite) {
// non-strict ref (chart name) // non-strict ref (chart name)
ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version) ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad basename)") suite.NotNil(err, "error pushing non-strict ref (bad basename)")
// non-strict ref (chart name), with strict mode disabled // non-strict ref (chart name), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptTest(true)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled") suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled")
// non-strict ref (chart version) // non-strict ref (chart version)
ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name) ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad tag)") suite.NotNil(err, "error pushing non-strict ref (bad tag)")
// non-strict ref (chart version), with strict mode disabled // non-strict ref (chart version), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptTest(true)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled") suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled")
// basic push, good ref // basic push, good ref
@ -251,7 +254,7 @@ func testPush(suite *TestSuite) {
meta, err = extractChartMeta(chartData) meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Nil(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptTest(true)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref") suite.Nil(err, "no error pushing good ref")
_, err = suite.RegistryClient.Pull(ref) _, err = suite.RegistryClient.Pull(ref)
@ -269,7 +272,7 @@ func testPush(suite *TestSuite) {
// push with prov // push with prov
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptTest(true)) result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref with prov") suite.Nil(err, "no error pushing good ref with prov")
_, err = suite.RegistryClient.Pull(ref) _, err = suite.RegistryClient.Pull(ref)
@ -281,12 +284,12 @@ func testPush(suite *TestSuite) {
suite.Equal(ref, result.Ref) suite.Equal(ref, result.Ref)
suite.Equal(meta.Name, result.Chart.Meta.Name) suite.Equal(meta.Name, result.Chart.Meta.Name)
suite.Equal(meta.Version, result.Chart.Meta.Version) suite.Equal(meta.Version, result.Chart.Meta.Version)
suite.Equal(int64(684), result.Manifest.Size) suite.Equal(int64(742), result.Manifest.Size)
suite.Equal(int64(99), result.Config.Size) suite.Equal(int64(99), result.Config.Size)
suite.Equal(int64(973), result.Chart.Size) suite.Equal(int64(973), result.Chart.Size)
suite.Equal(int64(695), result.Prov.Size) suite.Equal(int64(695), result.Prov.Size)
suite.Equal( suite.Equal(
"sha256:b57e8ffd938c43253f30afedb3c209136288e6b3af3b33473e95ea3b805888e6", "sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2",
result.Manifest.Digest) result.Manifest.Digest)
suite.Equal( suite.Equal(
"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580",
@ -354,12 +357,12 @@ func testPull(suite *TestSuite) {
suite.Equal(ref, result.Ref) suite.Equal(ref, result.Ref)
suite.Equal(meta.Name, result.Chart.Meta.Name) suite.Equal(meta.Name, result.Chart.Meta.Name)
suite.Equal(meta.Version, result.Chart.Meta.Version) suite.Equal(meta.Version, result.Chart.Meta.Version)
suite.Equal(int64(684), result.Manifest.Size) suite.Equal(int64(742), result.Manifest.Size)
suite.Equal(int64(99), result.Config.Size) suite.Equal(int64(99), result.Config.Size)
suite.Equal(int64(973), result.Chart.Size) suite.Equal(int64(973), result.Chart.Size)
suite.Equal(int64(695), result.Prov.Size) suite.Equal(int64(695), result.Prov.Size)
suite.Equal( suite.Equal(
"sha256:b57e8ffd938c43253f30afedb3c209136288e6b3af3b33473e95ea3b805888e6", "sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2",
result.Manifest.Digest) result.Manifest.Digest)
suite.Equal( suite.Equal(
"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580",
@ -370,7 +373,7 @@ func testPull(suite *TestSuite) {
suite.Equal( suite.Equal(
"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256", "sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256",
result.Prov.Digest) result.Prov.Digest)
suite.Equal("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}", suite.Equal("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.created\":\"1977-09-02T22:04:05Z\",\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}",
string(result.Manifest.Data)) string(result.Manifest.Data))
suite.Equal("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}", suite.Equal("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}",
string(result.Config.Data)) string(result.Config.Data))

@ -96,7 +96,7 @@ func (r *ChartRepository) Load() error {
// FIXME: Why are we recursively walking directories? // FIXME: Why are we recursively walking directories?
// FIXME: Why are we not reading the repositories.yaml to figure out // FIXME: Why are we not reading the repositories.yaml to figure out
// what repos to use? // what repos to use?
filepath.Walk(r.Config.Name, func(path string, f os.FileInfo, err error) error { filepath.Walk(r.Config.Name, func(path string, f os.FileInfo, _ error) error {
if !f.IsDir() { if !f.IsDir() {
if strings.Contains(f.Name(), "-index.yaml") { if strings.Contains(f.Name(), "-index.yaml") {
i, err := LoadIndexFile(path) i, err := LoadIndexFile(path)

@ -132,7 +132,7 @@ func TestIndexCustomSchemeDownload(t *testing.T) {
repoName := "gcs-repo" repoName := "gcs-repo"
repoURL := "gs://some-gcs-bucket" repoURL := "gs://some-gcs-bucket"
myCustomGetter := &CustomGetter{} myCustomGetter := &CustomGetter{}
customGetterConstructor := func(options ...getter.Option) (getter.Getter, error) { customGetterConstructor := func(_ ...getter.Option) (getter.Getter, error) {
return myCustomGetter, nil return myCustomGetter, nil
} }
providers := getter.Providers{{ providers := getter.Providers{{
@ -267,7 +267,7 @@ func startLocalServerForTests(handler http.Handler) (*httptest.Server, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler = http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Write(fileBytes) w.Write(fileBytes)
}) })
} }
@ -282,7 +282,7 @@ func startLocalTLSServerForTests(handler http.Handler) (*httptest.Server, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler = http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Write(fileBytes) w.Write(fileBytes)
}) })
} }

@ -61,7 +61,7 @@ func NewTempServerWithCleanupAndBasicAuth(t *testing.T, glob string) *Server {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
srv.WithMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { srv.WithMiddleware(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth() username, password, ok := r.BasicAuth()
if !ok || username != "username" || password != "password" { if !ok || username != "username" || password != "password" {
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password) t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)

@ -262,7 +262,7 @@ func newTestFixtureSQL(t *testing.T, _ ...*rspb.Release) (*SQL, sqlmock.Sqlmock)
sqlxDB := sqlx.NewDb(sqlDB, "sqlmock") sqlxDB := sqlx.NewDb(sqlDB, "sqlmock")
return &SQL{ return &SQL{
db: sqlxDB, db: sqlxDB,
Log: func(a string, b ...interface{}) {}, Log: func(_ string, _ ...interface{}) {},
namespace: "default", namespace: "default",
statementBuilder: sq.StatementBuilder.PlaceholderFormat(sq.Dollar), statementBuilder: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
}, mock }, mock

@ -98,9 +98,9 @@ func (s *SQL) Name() string {
// Check if all migrations al // Check if all migrations al
func (s *SQL) checkAlreadyApplied(migrations []*migrate.Migration) bool { func (s *SQL) checkAlreadyApplied(migrations []*migrate.Migration) bool {
// make map (set) of ids for fast search // make map (set) of ids for fast search
migrationsIds := make(map[string]struct{}) migrationsIDs := make(map[string]struct{})
for _, migration := range migrations { for _, migration := range migrations {
migrationsIds[migration.Id] = struct{}{} migrationsIDs[migration.Id] = struct{}{}
} }
// get list of applied migrations // get list of applied migrations
@ -113,15 +113,15 @@ func (s *SQL) checkAlreadyApplied(migrations []*migrate.Migration) bool {
} }
for _, record := range records { for _, record := range records {
if _, ok := migrationsIds[record.Id]; ok { if _, ok := migrationsIDs[record.Id]; ok {
s.Log("checkAlreadyApplied: found previous migration (Id: %v) applied at %v", record.Id, record.AppliedAt) s.Log("checkAlreadyApplied: found previous migration (Id: %v) applied at %v", record.Id, record.AppliedAt)
delete(migrationsIds, record.Id) delete(migrationsIDs, record.Id)
} }
} }
// check if all migrations appliyed // check if all migrations appliyed
if len(migrationsIds) != 0 { if len(migrationsIDs) != 0 {
for id := range migrationsIds { for id := range migrationsIDs {
s.Log("checkAlreadyApplied: find unapplied migration (id: %v)", id) s.Log("checkAlreadyApplied: find unapplied migration (id: %v)", id)
} }
return false return false

@ -546,31 +546,31 @@ func mockGetReleaseCustomLabels(mock sqlmock.Sqlmock, key string, namespace stri
func TestSqlChechkAppliedMigrations(t *testing.T) { func TestSqlChechkAppliedMigrations(t *testing.T) {
cases := []struct { cases := []struct {
migrationsToApply []*migrate.Migration migrationsToApply []*migrate.Migration
appliedMigrationsIds []string appliedMigrationsIDs []string
expectedResult bool expectedResult bool
errorExplanation string errorExplanation string
}{ }{
{ {
migrationsToApply: []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}}, migrationsToApply: []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}},
appliedMigrationsIds: []string{"1", "2", "init1", "3", "init2", "4", "5"}, appliedMigrationsIDs: []string{"1", "2", "init1", "3", "init2", "4", "5"},
expectedResult: false, expectedResult: false,
errorExplanation: "Has found one migration id \"init3\" as applied, that was not applied", errorExplanation: "Has found one migration id \"init3\" as applied, that was not applied",
}, },
{ {
migrationsToApply: []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}}, migrationsToApply: []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}},
appliedMigrationsIds: []string{"1", "2", "init1", "3", "init2", "4", "init3", "5"}, appliedMigrationsIDs: []string{"1", "2", "init1", "3", "init2", "4", "init3", "5"},
expectedResult: true, expectedResult: true,
errorExplanation: "Has not found one or more migration ids, that was applied", errorExplanation: "Has not found one or more migration ids, that was applied",
}, },
{ {
migrationsToApply: []*migrate.Migration{{Id: "init"}}, migrationsToApply: []*migrate.Migration{{Id: "init"}},
appliedMigrationsIds: []string{"1", "2", "3", "inits", "4", "tinit", "5"}, appliedMigrationsIDs: []string{"1", "2", "3", "inits", "4", "tinit", "5"},
expectedResult: false, expectedResult: false,
errorExplanation: "Has found single \"init\", that was not applied", errorExplanation: "Has found single \"init\", that was not applied",
}, },
{ {
migrationsToApply: []*migrate.Migration{{Id: "init"}}, migrationsToApply: []*migrate.Migration{{Id: "init"}},
appliedMigrationsIds: []string{"1", "2", "init", "3", "init2", "4", "init3", "5"}, appliedMigrationsIDs: []string{"1", "2", "init", "3", "init2", "4", "init3", "5"},
expectedResult: true, expectedResult: true,
errorExplanation: "Has not found single migration id \"init\", that was applied", errorExplanation: "Has not found single migration id \"init\", that was applied",
}, },
@ -578,7 +578,7 @@ func TestSqlChechkAppliedMigrations(t *testing.T) {
for i, c := range cases { for i, c := range cases {
sqlDriver, mock := newTestFixtureSQL(t) sqlDriver, mock := newTestFixtureSQL(t)
rows := sqlmock.NewRows([]string{"id", "applied_at"}) rows := sqlmock.NewRows([]string{"id", "applied_at"})
for _, id := range c.appliedMigrationsIds { for _, id := range c.appliedMigrationsIDs {
rows.AddRow(id, time.Time{}) rows.AddRow(id, time.Time{})
} }
mock. mock.

@ -0,0 +1,25 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ctime
import (
"os"
"time"
)
func Created(fi os.FileInfo) time.Time {
return created(fi)
}

@ -0,0 +1,30 @@
//go:build linux
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ctime
import (
"os"
"syscall"
"time"
)
func created(fi os.FileInfo) time.Time {
st := fi.Sys().(*syscall.Stat_t)
//nolint
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec))
}

@ -0,0 +1,27 @@
//go:build !linux
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ctime
import (
"os"
"time"
)
func created(fi os.FileInfo) time.Time {
return fi.ModTime()
}
Loading…
Cancel
Save