Merge branch 'helm:main' into feature/enhance-dry-run-for-helm-4

pull/31616/head
MrJack 3 weeks ago committed by GitHub
commit 9c3f70ea4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -55,7 +55,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif

@ -25,6 +25,7 @@ linters:
- ineffassign
- misspell
- nakedret
- nolintlint
- revive
- sloglint
- staticcheck
@ -67,6 +68,9 @@ linters:
dupl:
threshold: 400
exhaustive:
default-signifies-exhaustive: true
gomodguard:
blocked:
modules:
@ -74,8 +78,8 @@ linters:
recommendations:
- github.com/evanphx/json-patch/v5
exhaustive:
default-signifies-exhaustive: true
nolintlint:
require-specific: true
run:
timeout: 10m

@ -1,48 +1,88 @@
# AGENTS.md
## Overview
Helm is a package manager for Kubernetes written in Go, supporting v3 (stable) and v4 (unstable) APIs.
## Build & Test
Helm is a package manager for Kubernetes written in Go. It enables users to define, install, and upgrade complex Kubernetes applications using charts.
This document provides an overview of the codebase structure, development guidelines, and key patterns for contributors.
The codebase supports both an SDK for advanced users, and a CLI for direct end user usage.
The project currently supports Helm v3 and Helm v4 versions, based on the `dev-v3` and `main` branches respectively.
## Build and test
```bash
make build # Build binary
make test # Run all tests (style + unit)
make test-unit # Unit tests only
make test-coverage # With coverage
make test-style # Linting
golangci-lint run # Direct linting
make test-style # Linting (wraps golangci-lint)
go test -run TestName # Specific test
```
## Code Structure
- `/cmd/helm/` - CLI entry point (Cobra-based)
- `/pkg/` - Public API
## Code structure
Major packages:
- `cmd/helm/` - CLI entry point, wires CLI flags to `pkg/cmd/` commands
- `pkg/` - Public API
- `action/` - Core operations (install, upgrade, rollback)
- `cmd/` - Cobra command implementations bridging CLI flags to `pkg/action/`
- `chart/v2/` - Stable chart format
- `engine/` - Template rendering (Go templates + Sprig)
- `kube/` - Kubernetes client abstraction layer
- `registry/` - OCI support
- `release/` - Release types and interfaces (`v1/`, `common/`)
- `repo/` - Chart repository indexing and interaction
- `storage/` - Release backends (Secrets/ConfigMaps/SQL)
- `/internal/` - Private implementation
- `internal/` - Private implementations
- `chart/v3/` - Next-gen chart format
- `release/v2/` - Release package for chart v3 support
## Development
### Compatibility
Changes are required to maintain backward compatibility as described in [HIP-0004: Document backwards-compatibility rules](https://github.com/helm/community/blob/main/hips/hip-0004.md).
Typically this means that:
## Development Guidelines
- the signatures of public APIs, i.e., those in the `pkg/` directory should not change
- CLI commands and parameters should not be removed or changed in a way that would break existing scripts or workflows
- functional behaviour (as implied or documented) must not be modified in a way that would break existing users' expectations
An exception to the above is where incompatible changes are needed to fix a security vulnerability, where minimal breaking changes may be made to address the issue.
### Code standards
### Code Standards
- Use table-driven tests with testify
- Golden files in `testdata/` for complex output
- Mock Kubernetes clients for action tests
- All commits must include DCO sign-off: `git commit -s`
### Branching
- `main` - Helm v4 development
- `dev-v3` - Helm v3 stable (backport from main)
### Dependencies
Standard workflow is for PR development changes to the `main` branch. Minor release branches are cut from `main`, then maintained for critical fixes via patch releases.
Bug and security fixes are also backported to `dev-v3` where applicable.
Development branches:
- `main` - Helm v4
- `dev-v3` - Helm v3 (backport security and bugfixes from main)
Release branches:
- `release-v3.X` - Release branches for v3.X versions
- `release-v4.X` - Release branches for v4.X versions
### Major dependencies
- `k8s.io/client-go` - Kubernetes interaction
- `github.com/spf13/cobra` - CLI framework
- `github.com/Masterminds/sprig` - Template functions
### Key Patterns
- **Actions**: Operations in `/pkg/action/` use shared Configuration
- **Dual Chart Support**: v2 (stable) in `/pkg/`, v3 (dev) in `/internal/`
- **Storage Abstraction**: Pluggable release storage backends
### Key patterns
- **Actions**: High-level operations live in `pkg/action/`, typically using a shared Configuration
- **Chart versions**: Charts v2 (stable) in `pkg/chart/v2`, v3 (under development) in `internal/chart/v3`
- **Plugins and extensibility**: Enabling additional functionality via plugins and extension points, such as custom template functions or storage backends is preferred over incorporating into Helm's codebase

@ -49,7 +49,7 @@ type Chart struct {
// Schema is an optional JSON schema for imposing structure on Values
Schema []byte `json:"schema"`
// SchemaModTime the schema was last modified
SchemaModTime time.Time `json:"schemamodtime,omitempty"`
SchemaModTime time.Time `json:"schemamodtime"`
// Files are miscellaneous files in a chart archive,
// e.g. README, LICENSE, etc.
Files []*common.File `json:"files"`

@ -231,7 +231,7 @@ func TestMalformedTemplate(t *testing.T) {
}()
select {
case <-c:
t.Fatalf("lint malformed template timeout")
t.Fatal("lint malformed template timeout")
case <-ch:
if len(m) != 1 {
t.Fatalf("All didn't fail with expected errors, got %#v", m)

@ -152,7 +152,7 @@ func validateChartVersion(cf *chart.Metadata) error {
valid, msg := c.Validate(version)
if !valid && len(msg) > 0 {
return fmt.Errorf("version %v", msg[0])
return fmt.Errorf("version %w", msg[0])
}
return nil

@ -19,7 +19,6 @@ package rules
import (
"bytes"
"errors"
"fmt"
"io"
"io/fs"
"os"
@ -102,14 +101,14 @@ func validateCrdsDir(crdsPath string) error {
func validateCrdAPIVersion(obj *k8sYamlStruct) error {
if !strings.HasPrefix(obj.APIVersion, "apiextensions.k8s.io") {
return fmt.Errorf("apiVersion is not in 'apiextensions.k8s.io'")
return errors.New("apiVersion is not in 'apiextensions.k8s.io'")
}
return nil
}
func validateCrdKind(obj *k8sYamlStruct) error {
if obj.Kind != "CustomResourceDefinition" {
return fmt.Errorf("object kind is not 'CustomResourceDefinition'")
return errors.New("object kind is not 'CustomResourceDefinition'")
}
return nil
}

@ -17,6 +17,7 @@ limitations under the License.
package rules
import (
"errors"
"fmt"
"os"
"path/filepath"
@ -47,7 +48,7 @@ func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]any,
func validateValuesFileExistence(valuesPath string) error {
_, err := os.Stat(valuesPath)
if err != nil {
return fmt.Errorf("file does not exist")
return errors.New("file does not exist")
}
return nil
}

@ -57,7 +57,7 @@ func LoadFile(name string) (*chart.Chart, error) {
c, err := LoadArchive(raw)
if err != nil {
if errors.Is(err, gzip.ErrHeader) {
return nil, fmt.Errorf("file '%s' does not appear to be a valid chart file (details: %s)", name, err)
return nil, fmt.Errorf("file '%s' does not appear to be a valid chart file (details: %w)", name, err)
}
}
return c, err

@ -16,6 +16,7 @@ limitations under the License.
package v3
import (
"errors"
"testing"
)
@ -181,7 +182,7 @@ func TestValidate(t *testing.T) {
for _, tt := range tests {
result := tt.md.Validate()
if result != tt.err {
if !errors.Is(result, tt.err) {
t.Errorf("expected %q, got %q in test %q", tt.err, result, tt.name)
}
}

@ -35,7 +35,7 @@ func TestLoadChartfile(t *testing.T) {
func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
t.Helper()
if f == nil { //nolint:staticcheck
if f == nil {
t.Fatal("Failed verifyChartfile because f is nil")
}
@ -64,7 +64,7 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
}
if len(f.Sources) != 1 {
t.Fatalf("Unexpected number of sources")
t.Fatal("Unexpected number of sources")
}
if f.Sources[0] != "https://example.com/foo/bar" {
@ -84,7 +84,7 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
}
if len(f.Annotations) != 2 {
t.Fatalf("Unexpected annotations")
t.Fatal("Unexpected annotations")
}
if want, got := "extravalue", f.Annotations["extrakey"]; want != got {

@ -63,7 +63,7 @@ func TestLoadDependency(t *testing.T) {
}
func TestDependencyEnabled(t *testing.T) {
type M = map[string]interface{}
type M = map[string]any
tests := []struct {
name string
v M
@ -385,7 +385,7 @@ func TestGetAliasDependency(t *testing.T) {
req := c.Metadata.Dependencies
if len(req) == 0 {
t.Fatalf("there are no dependencies to test")
t.Fatal("there are no dependencies to test")
}
// Success case
@ -403,7 +403,7 @@ func TestGetAliasDependency(t *testing.T) {
if req[0].Version != "" {
if !IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
t.Fatalf("dependency chart version is not in the compatible range")
t.Fatal("dependency chart version is not in the compatible range")
}
}
@ -415,7 +415,7 @@ func TestGetAliasDependency(t *testing.T) {
req[0].Version = "something else which is not in the compatible range"
if IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
t.Fatalf("dependency chart version which is not in the compatible range should cause a failure other than a success ")
t.Fatal("dependency chart version outside the compatible range should not be considered compatible")
}
}

@ -21,8 +21,8 @@ import (
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path"
@ -87,7 +87,7 @@ func TestSave(t *testing.T) {
t.Fatalf("Schema data did not match.\nExpected:\n%s\nActual:\n%s", formattedExpected, formattedActual)
}
if _, err := Save(&chartWithInvalidJSON, dest); err == nil {
t.Fatalf("Invalid JSON was not caught while saving chart")
t.Fatal("Invalid JSON was not caught while saving chart")
}
c.Metadata.APIVersion = chart.APIVersionV3
@ -153,7 +153,7 @@ func TestSavePreservesTimestamps(t *testing.T) {
Version: "1.2.3",
},
ModTime: initialCreateTime,
Values: map[string]interface{}{
Values: map[string]any{
"imageName": "testimage",
"imageId": 42,
},
@ -353,5 +353,5 @@ func sha256Sum(filePath string) (string, error) {
return "", err
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
return hex.EncodeToString(h.Sum(nil)), nil
}

@ -17,6 +17,7 @@ package installer // import "helm.sh/helm/v4/internal/plugin/installer"
import (
"bytes"
"errors"
"fmt"
"log/slog"
"os"
@ -143,7 +144,7 @@ func (i *HTTPInstaller) Install() error {
// Update updates a local repository
// Not implemented for now since tarball most likely will be packaged by version
func (i *HTTPInstaller) Update() error {
return fmt.Errorf("method Update() not implemented for HttpInstaller")
return errors.New("method Update() not implemented for HttpInstaller")
}
// Path is overridden because we want to join on the plugin name not the file name
@ -163,7 +164,7 @@ func (i *HTTPInstaller) SupportsVerification() bool {
// GetVerificationData returns cached plugin and provenance data for verification
func (i *HTTPInstaller) GetVerificationData() (archiveData, provData []byte, filename string, err error) {
if !i.SupportsVerification() {
return nil, nil, "", fmt.Errorf("verification not supported for this source")
return nil, nil, "", errors.New("verification not supported for this source")
}
// Download plugin data once and cache it

@ -150,7 +150,7 @@ func TestHTTPInstallerNonExistentVersion(t *testing.T) {
// inject fake http client responding with error
httpInstaller.getter = &TestHTTPGetter{
MockError: fmt.Errorf("failed to download plugin for some reason"),
MockError: errors.New("failed to download plugin for some reason"),
}
// attempt to install the plugin

@ -87,7 +87,7 @@ func InstallWithOptions(i Installer, opts Options) (*VerificationResult, error)
if opts.Verify {
verifier, ok := i.(Verifier)
if !ok || !verifier.SupportsVerification() {
return nil, fmt.Errorf("--verify is only supported for plugin tarballs (.tgz files)")
return nil, errors.New("--verify is only supported for plugin tarballs (.tgz files)")
}
// Get verification data (works for both memory and file-based installers)
@ -137,7 +137,7 @@ func Update(i Installer) error {
// NewForSource determines the correct Installer for the given source.
func NewForSource(source, version string) (installer Installer, err error) {
if strings.HasPrefix(source, fmt.Sprintf("%s://", registry.OCIScheme)) {
if strings.HasPrefix(source, registry.OCIScheme+"://") {
// Source is an OCI registry reference
installer, err = NewOCIInstaller(source)
} else if isLocalReference(source) {

@ -188,7 +188,7 @@ func (i *LocalInstaller) SupportsVerification() bool {
// GetVerificationData loads plugin and provenance data from local files for verification
func (i *LocalInstaller) GetVerificationData() (archiveData, provData []byte, filename string, err error) {
if !i.SupportsVerification() {
return nil, nil, "", fmt.Errorf("verification not supported for directories")
return nil, nil, "", errors.New("verification not supported for directories")
}
// Read and cache the plugin archive file

@ -19,6 +19,7 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"errors"
"os"
"path/filepath"
"testing"
@ -64,7 +65,7 @@ func TestLocalInstallerNotAFolder(t *testing.T) {
if err == nil {
t.Fatal("expected error")
}
if err != ErrPluginNotADirectory {
if !errors.Is(err, ErrPluginNotADirectory) {
t.Fatalf("expected error to equal: %q", err)
}
}

@ -130,7 +130,7 @@ func (i *OCIInstaller) Install() error {
// Check if this is a gzip compressed file
if len(i.pluginData) < 2 || i.pluginData[0] != 0x1f || i.pluginData[1] != 0x8b {
return fmt.Errorf("plugin data is not a gzip compressed archive")
return errors.New("plugin data is not a gzip compressed archive")
}
// Create cache directory

@ -82,7 +82,7 @@ command: "$HELM_PLUGIN_DIR/bin/%s"
// Add executable
execContent := fmt.Sprintf("#!/bin/sh\necho '%s test plugin'", pluginName)
execHeader := &tar.Header{
Name: fmt.Sprintf("bin/%s", pluginName),
Name: "bin/" + pluginName,
Mode: 0755,
Size: int64(len(execContent)),
Typeflag: tar.TypeReg,

@ -90,14 +90,14 @@ func TestVCSInstaller(t *testing.T) {
// Install again to test plugin exists error
if err := Install(i); err == nil {
t.Fatalf("expected error for plugin exists, got none")
t.Fatal("expected error for plugin exists, got none")
} else if err.Error() != "plugin already exists" {
t.Fatalf("expected error for plugin exists, got (%v)", err)
}
// Testing FindSource method, expect error because plugin code is not a cloned repository
if _, err := FindSource(i.Path()); err == nil {
t.Fatalf("expected error for inability to find plugin source, got none")
t.Fatal("expected error for inability to find plugin source, got none")
} else if err.Error() != "cannot get information about plugin source" {
t.Fatalf("expected error for inability to find plugin source, got (%v)", err)
}
@ -120,7 +120,7 @@ func TestVCSInstallerNonExistentVersion(t *testing.T) {
}
if err := Install(i); err == nil {
t.Fatalf("expected error for version does not exists, got none")
t.Fatal("expected error for version does not exists, got none")
} else if strings.Contains(err.Error(), "Could not resolve host: github.com") {
t.Skip("Unable to run test without Internet access")
} else if err.Error() != fmt.Sprintf("requested version %q does not exist for plugin %q", version, source) {
@ -181,7 +181,7 @@ func TestVCSInstallerUpdate(t *testing.T) {
}
// Testing update for error
if err := Update(vcsInstaller); err == nil {
t.Fatalf("expected error for plugin modified, got none")
t.Fatal("expected error for plugin modified, got none")
} else if err.Error() != "plugin repo was modified" {
t.Fatalf("expected error for plugin modified, got (%v)", err)
}

@ -107,7 +107,7 @@ func TestInstallWithOptions_VerifyWithValidProvenance(t *testing.T) {
// Should fail due to invalid signature (empty keyring) but we test that it gets past the hash check
if err == nil {
t.Fatalf("Expected installation to fail with empty keyring")
t.Fatal("Expected installation to fail with empty keyring")
}
if !strings.Contains(err.Error(), "plugin verification failed") {
t.Errorf("Expected plugin verification failed error, got: %v", err)
@ -218,7 +218,7 @@ func TestInstallWithOptions_VerifyDirectoryNotSupported(t *testing.T) {
// Should fail with verification not supported error
if err == nil {
t.Fatalf("Expected installation to fail with verification not supported error")
t.Fatal("Expected installation to fail with verification not supported error")
}
if !strings.Contains(err.Error(), "--verify is only supported for plugin tarballs") {
t.Errorf("Expected verification not supported error, got: %v", err)
@ -257,7 +257,7 @@ func TestInstallWithOptions_VerifyMismatchedProvenance(t *testing.T) {
// Should fail with verification error
if err == nil {
t.Fatalf("Expected installation to fail with hash mismatch")
t.Fatal("Expected installation to fail with hash mismatch")
}
if !strings.Contains(err.Error(), "plugin verification failed") {
t.Errorf("Expected plugin verification failed error, got: %v", err)
@ -298,7 +298,7 @@ func TestInstallWithOptions_VerifyProvenanceAccessError(t *testing.T) {
// Should fail with access error (either at stat level or during verification)
if err == nil {
t.Fatalf("Expected installation to fail with provenance file access error")
t.Fatal("Expected installation to fail with provenance file access error")
}
// The error could be either "failed to access provenance file" or "plugin verification failed"
// depending on when the permission error occurs

@ -17,7 +17,6 @@ package plugin
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
@ -71,7 +70,7 @@ func TestLoadDir(t *testing.T) {
}
return Metadata{
APIVersion: apiVersion,
Name: fmt.Sprintf("hello-%s", apiVersion),
Name: "hello-" + apiVersion,
Version: "0.1.0",
Type: "cli/v1",
Runtime: "subprocess",

@ -58,23 +58,23 @@ func (m Metadata) Validate() error {
}
if m.APIVersion == "" {
errs = append(errs, fmt.Errorf("empty APIVersion"))
errs = append(errs, errors.New("empty APIVersion"))
}
if m.Type == "" {
errs = append(errs, fmt.Errorf("empty type field"))
errs = append(errs, errors.New("empty type field"))
}
if m.Runtime == "" {
errs = append(errs, fmt.Errorf("empty runtime field"))
errs = append(errs, errors.New("empty runtime field"))
}
if m.Config == nil {
errs = append(errs, fmt.Errorf("missing config field"))
errs = append(errs, errors.New("missing config field"))
}
if m.RuntimeConfig == nil {
errs = append(errs, fmt.Errorf("missing runtimeConfig field"))
errs = append(errs, errors.New("missing runtimeConfig field"))
}
// Validate the config itself

@ -16,6 +16,7 @@ limitations under the License.
package plugin
import (
"errors"
"fmt"
"strings"
"unicode"
@ -74,11 +75,11 @@ func (m *MetadataLegacy) Validate() error {
m.Usage = sanitizeString(m.Usage)
if len(m.PlatformCommand) > 0 && len(m.Command) > 0 {
return fmt.Errorf("both platformCommand and command are set")
return errors.New("both platformCommand and command are set")
}
if len(m.PlatformHooks) > 0 && len(m.Hooks) > 0 {
return fmt.Errorf("both platformHooks and hooks are set")
return errors.New("both platformHooks and hooks are set")
}
// Validate downloader plugins

@ -16,6 +16,7 @@ limitations under the License.
package plugin
import (
"errors"
"fmt"
)
@ -48,7 +49,7 @@ type MetadataV1 struct {
func (m *MetadataV1) Validate() error {
if !validPluginName.MatchString(m.Name) {
return fmt.Errorf("invalid plugin `name`")
return errors.New("invalid plugin `name`")
}
if m.APIVersion != "v1" {
@ -56,11 +57,11 @@ func (m *MetadataV1) Validate() error {
}
if m.Type == "" {
return fmt.Errorf("`type` missing")
return errors.New("`type` missing")
}
if m.Runtime == "" {
return fmt.Errorf("`runtime` missing")
return errors.New("`runtime` missing")
}
return nil

@ -117,8 +117,8 @@ func (r *SubprocessPluginRuntime) InvokeWithEnv(main string, argv []string, env
cmd.Env = slices.Clone(os.Environ())
cmd.Env = append(
cmd.Env,
fmt.Sprintf("HELM_PLUGIN_NAME=%s", r.metadata.Name),
fmt.Sprintf("HELM_PLUGIN_DIR=%s", r.pluginDir))
"HELM_PLUGIN_NAME="+r.metadata.Name,
"HELM_PLUGIN_DIR="+r.pluginDir)
cmd.Env = append(cmd.Env, env...)
cmd.Stdin = stdin

@ -24,6 +24,7 @@ import (
"os/exec"
"path/filepath"
"slices"
"strconv"
"helm.sh/helm/v4/internal/plugin/schema"
)
@ -63,7 +64,7 @@ func (r *SubprocessPluginRuntime) runGetter(input *Input) (*Output, error) {
env["HELM_PLUGIN_DIR"] = r.pluginDir
env["HELM_PLUGIN_USERNAME"] = msg.Options.Username
env["HELM_PLUGIN_PASSWORD"] = msg.Options.Password
env["HELM_PLUGIN_PASS_CREDENTIALS_ALL"] = fmt.Sprintf("%t", msg.Options.PassCredentialsAll)
env["HELM_PLUGIN_PASS_CREDENTIALS_ALL"] = strconv.FormatBool(msg.Options.PassCredentialsAll)
command, args, err := PrepareCommands(d.PlatformCommand, false, []string{}, env)
if err != nil {

@ -14,6 +14,7 @@
package schema
import (
"errors"
"fmt"
"time"
)
@ -55,7 +56,7 @@ type ConfigGetterV1 struct {
func (c *ConfigGetterV1) Validate() error {
if len(c.Protocols) == 0 {
return fmt.Errorf("getter has no protocols")
return errors.New("getter has no protocols")
}
for i, protocol := range c.Protocols {
if protocol == "" {

@ -23,7 +23,7 @@ import (
"path/filepath"
"strings"
"github.com/ProtonMail/go-crypto/openpgp/clearsign" //nolint
"github.com/ProtonMail/go-crypto/openpgp/clearsign"
"helm.sh/helm/v4/pkg/helmpath"
)

@ -16,7 +16,7 @@ limitations under the License.
package plugin
import (
"fmt"
"errors"
"os"
"runtime"
"strings"
@ -80,7 +80,7 @@ func getPlatformCommand(cmds []PlatformCommand) ([]string, []string) {
func PrepareCommands(cmds []PlatformCommand, expandArgs bool, extraArgs []string, env map[string]string) (string, []string, error) {
cmdParts, args := getPlatformCommand(cmds)
if len(cmdParts) == 0 || cmdParts[0] == "" {
return "", nil, fmt.Errorf("no plugin command is applicable")
return "", nil, errors.New("no plugin command is applicable")
}
envMappingFunc := func(key string) string {
return env[key]

@ -210,7 +210,7 @@ func TestPrepareCommandsNoMatch(t *testing.T) {
env := map[string]string{}
if _, _, err := PrepareCommands(cmds, true, []string{}, env); err == nil {
t.Fatalf("Expected error to be returned")
t.Fatal("Expected error to be returned")
}
}
@ -219,7 +219,7 @@ func TestPrepareCommandsNoCommands(t *testing.T) {
env := map[string]string{}
if _, _, err := PrepareCommands(cmds, true, []string{}, env); err == nil {
t.Fatalf("Expected error to be returned")
t.Fatal("Expected error to be returned")
}
}

@ -86,7 +86,7 @@ type Hook struct {
// Events are the events that this hook fires on.
Events []HookEvent `json:"events,omitempty"`
// LastRun indicates the date/time this was last run.
LastRun HookExecution `json:"last_run,omitempty"`
LastRun HookExecution `json:"last_run"`
// Weight indicates the sort order for execution among similar Hook type
Weight int `json:"weight,omitempty"`
// DeletePolicies are the policies that indicate when to delete the hook
@ -133,7 +133,7 @@ type hookExecutionJSON struct {
// It handles empty string time fields by treating them as zero values.
func (h *HookExecution) UnmarshalJSON(data []byte) error {
// First try to unmarshal into a map to handle empty string time fields
var raw map[string]interface{}
var raw map[string]any
if err := json.Unmarshal(data, &raw); err != nil {
return err
}

@ -220,7 +220,7 @@ func TestHookExecutionEmptyStringRoundTrip(t *testing.T) {
data, err := json.Marshal(&exec)
require.NoError(t, err)
var result map[string]interface{}
var result map[string]any
err = json.Unmarshal(data, &result)
require.NoError(t, err)

@ -57,7 +57,7 @@ type infoJSON struct {
// It handles empty string time fields by treating them as zero values.
func (i *Info) UnmarshalJSON(data []byte) error {
// First try to unmarshal into a map to handle empty string time fields
var raw map[string]interface{}
var raw map[string]any
if err := json.Unmarshal(data, &raw); err != nil {
return err
}

@ -272,7 +272,7 @@ func TestInfoEmptyStringRoundTrip(t *testing.T) {
data, err := json.Marshal(&info)
require.NoError(t, err)
var result map[string]interface{}
var result map[string]any
err = json.Unmarshal(data, &result)
require.NoError(t, err)

@ -17,8 +17,8 @@ limitations under the License.
package v2
import (
"fmt"
"math/rand"
"strconv"
"time"
v3 "helm.sh/helm/v4/internal/chart/v3"
@ -57,7 +57,7 @@ func Mock(opts *MockReleaseOptions) *Release {
name := opts.Name
if name == "" {
name = "testrelease-" + fmt.Sprint(rand.Intn(100))
name = "testrelease-" + strconv.Itoa(rand.Intn(100))
}
version := 1
@ -124,7 +124,7 @@ func Mock(opts *MockReleaseOptions) *Release {
Name: name,
Info: info,
Chart: ch,
Config: map[string]interface{}{"name": "value"},
Config: map[string]any{"name": "value"},
Version: version,
Namespace: namespace,
Hooks: []*Hook{

@ -36,7 +36,7 @@ type Release struct {
Chart *chart.Chart `json:"chart,omitempty"`
// Config is the set of extra Values added to the chart.
// These values override the default values inside of the chart.
Config map[string]interface{} `json:"config,omitempty"`
Config map[string]any `json:"config,omitempty"`
// Manifest is the string representation of the rendered template.
Manifest string `json:"manifest,omitempty"`
// Hooks are all of the hooks declared for this release.

@ -137,7 +137,7 @@ func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.H
return h
}
func lessByKind(_ interface{}, _ interface{}, kindA string, kindB string, o KindSortOrder) bool {
func lessByKind(_ any, _ any, kindA string, kindB string, o KindSortOrder) bool {
ordering := make(map[string]int, len(o))
for v, k := range o {
ordering[k] = v

@ -149,7 +149,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string
} else {
// Retrieve list of tags for repository
ref := fmt.Sprintf("%s/%s", strings.TrimPrefix(d.Repository, fmt.Sprintf("%s://", registry.OCIScheme)), d.Name)
ref := fmt.Sprintf("%s/%s", strings.TrimPrefix(d.Repository, registry.OCIScheme+"://"), d.Name)
tags, err := r.registryClient.Tags(ref)
if err != nil {
return nil, fmt.Errorf("could not retrieve list of tags for repository %s: %w", d.Repository, err)

@ -112,7 +112,7 @@ func NewTLSConfig(options ...TLSConfigOption) (*tls.Config, error) {
if len(to.caPEMBlock) > 0 {
cp := x509.NewCertPool()
if !cp.AppendCertsFromPEM(to.caPEMBlock) {
return nil, fmt.Errorf("failed to append certificates from pem block")
return nil, errors.New("failed to append certificates from pem block")
}
config.RootCAs = cp

@ -58,10 +58,10 @@ func TestNewTLSConfig(t *testing.T) {
t.Fatalf("expecting 1 client certificates, got %d", got)
}
if cfg.InsecureSkipVerify {
t.Fatalf("insecure skip verify mismatch, expecting false")
t.Fatal("insecure skip verify mismatch, expecting false")
}
if cfg.RootCAs == nil {
t.Fatalf("mismatch tls RootCAs, expecting non-nil")
t.Fatal("mismatch tls RootCAs, expecting non-nil")
}
}
{
@ -77,10 +77,10 @@ func TestNewTLSConfig(t *testing.T) {
t.Fatalf("expecting 0 client certificates, got %d", got)
}
if cfg.InsecureSkipVerify {
t.Fatalf("insecure skip verify mismatch, expecting false")
t.Fatal("insecure skip verify mismatch, expecting false")
}
if cfg.RootCAs == nil {
t.Fatalf("mismatch tls RootCAs, expecting non-nil")
t.Fatal("mismatch tls RootCAs, expecting non-nil")
}
}
@ -97,10 +97,10 @@ func TestNewTLSConfig(t *testing.T) {
t.Fatalf("expecting 1 client certificates, got %d", got)
}
if cfg.InsecureSkipVerify {
t.Fatalf("insecure skip verify mismatch, expecting false")
t.Fatal("insecure skip verify mismatch, expecting false")
}
if cfg.RootCAs != nil {
t.Fatalf("mismatch tls RootCAs, expecting nil")
t.Fatal("mismatch tls RootCAs, expecting nil")
}
}
}

@ -17,7 +17,7 @@ limitations under the License.
package version
import (
"fmt"
"errors"
"runtime/debug"
"slices"
@ -27,7 +27,7 @@ import (
func K8sIOClientGoModVersion() (string, error) {
info, ok := debug.ReadBuildInfo()
if !ok {
return "", fmt.Errorf("failed to read build info")
return "", errors.New("failed to read build info")
}
idx := slices.IndexFunc(info.Deps, func(m *debug.Module) bool {
@ -35,7 +35,7 @@ func K8sIOClientGoModVersion() (string, error) {
})
if idx == -1 {
return "", fmt.Errorf("k8s.io/client-go not found in build info")
return "", errors.New("k8s.io/client-go not found in build info")
}
m := info.Deps[idx]

@ -466,7 +466,7 @@ func GetVersionSet(client discovery.ServerResourcesInterface) (common.VersionSet
return common.DefaultVersionSet, nil
}
versionMap := make(map[string]interface{})
versionMap := make(map[string]any)
var versions []string
// Extract the groups

@ -157,12 +157,12 @@ func withName(name string) chartOption {
}
func withSampleValues() chartOption {
values := map[string]interface{}{
values := map[string]any{
"someKey": "someValue",
"nestedKey": map[string]interface{}{
"nestedKey": map[string]any{
"simpleKey": "simpleValue",
"anotherNestedKey": map[string]interface{}{
"yetAnotherNestedKey": map[string]interface{}{
"anotherNestedKey": map[string]any{
"yetAnotherNestedKey": map[string]any{
"youReadyForAnotherNestedKey": "No",
},
},
@ -173,7 +173,7 @@ func withSampleValues() chartOption {
}
}
func withValues(values map[string]interface{}) chartOption {
func withValues(values map[string]any) chartOption {
return func(opts *chartOptions) {
opts.Values = values
}
@ -274,7 +274,7 @@ func namedReleaseStub(name string, status rcommon.Status) *release.Release {
Description: "Named Release Stub",
},
Chart: buildChart(withSampleTemplates()),
Config: map[string]interface{}{"name": "value"},
Config: map[string]any{"name": "value"},
Version: 1,
Hooks: []*release.Hook{
{
@ -304,7 +304,7 @@ func TestConfiguration_Init(t *testing.T) {
tests := []struct {
name string
helmDriver string
expectedDriverType interface{}
expectedDriverType any
expectErr bool
errMsg string
}{
@ -795,7 +795,7 @@ func TestRenderResources_PostRenderer_Success(t *testing.T) {
}
ch := buildChart(withSampleTemplates())
values := map[string]interface{}{}
values := map[string]any{}
hooks, buf, notes, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,
@ -838,7 +838,7 @@ func TestRenderResources_PostRenderer_Error(t *testing.T) {
}
ch := buildChart(withSampleTemplates())
values := map[string]interface{}{}
values := map[string]any{}
_, _, _, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,
@ -866,7 +866,7 @@ func TestRenderResources_PostRenderer_MergeError(t *testing.T) {
{Name: "templates/invalid", ModTime: time.Now(), Data: []byte("invalid: yaml: content:")},
},
}
values := map[string]interface{}{}
values := map[string]any{}
_, _, _, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,
@ -888,7 +888,7 @@ func TestRenderResources_PostRenderer_SplitError(t *testing.T) {
}
ch := buildChart(withSampleTemplates())
values := map[string]interface{}{}
values := map[string]any{}
_, _, _, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,
@ -909,7 +909,7 @@ func TestRenderResources_PostRenderer_Integration(t *testing.T) {
}
ch := buildChart(withSampleTemplates())
values := map[string]interface{}{}
values := map[string]any{}
hooks, buf, notes, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,
@ -945,7 +945,7 @@ func TestRenderResources_NoPostRenderer(t *testing.T) {
cfg := actionConfigFixture(t)
ch := buildChart(withSampleTemplates())
values := map[string]interface{}{}
values := map[string]any{}
hooks, buf, notes, err := cfg.renderResources(
ch, values, "test-release", "", false, false, false,

@ -42,7 +42,7 @@ func NewGetValues(cfg *Configuration) *GetValues {
}
// Run executes 'helm get values' against the given release.
func (g *GetValues) Run(name string) (map[string]interface{}, error) {
func (g *GetValues) Run(name string) (map[string]any, error) {
if err := g.cfg.KubeClient.IsReachable(); err != nil {
return nil, err
}

@ -45,12 +45,12 @@ func TestGetValues_Run_UserConfigOnly(t *testing.T) {
client := NewGetValues(cfg)
releaseName := "test-release"
userConfig := map[string]interface{}{
"database": map[string]interface{}{
userConfig := map[string]any{
"database": map[string]any{
"host": "localhost",
"port": 5432,
},
"app": map[string]interface{}{
"app": map[string]any{
"name": "my-app",
"replicas": 3,
},
@ -66,9 +66,9 @@ func TestGetValues_Run_UserConfigOnly(t *testing.T) {
Name: "test-chart",
Version: "1.0.0",
},
Values: map[string]interface{}{
Values: map[string]any{
"defaultKey": "defaultValue",
"app": map[string]interface{}{
"app": map[string]any{
"name": "default-app",
"timeout": 30,
},
@ -92,19 +92,19 @@ func TestGetValues_Run_AllValues(t *testing.T) {
client.AllValues = true
releaseName := "test-release"
userConfig := map[string]interface{}{
"database": map[string]interface{}{
userConfig := map[string]any{
"database": map[string]any{
"host": "localhost",
"port": 5432,
},
"app": map[string]interface{}{
"app": map[string]any{
"name": "my-app",
},
}
chartDefaultValues := map[string]interface{}{
chartDefaultValues := map[string]any{
"defaultKey": "defaultValue",
"app": map[string]interface{}{
"app": map[string]any{
"name": "default-app",
"timeout": 30,
},
@ -132,11 +132,11 @@ func TestGetValues_Run_AllValues(t *testing.T) {
result, err := client.Run(releaseName)
require.NoError(t, err)
assert.Equal(t, "my-app", result["app"].(map[string]interface{})["name"])
assert.Equal(t, 30, result["app"].(map[string]interface{})["timeout"])
assert.Equal(t, "my-app", result["app"].(map[string]any)["name"])
assert.Equal(t, 30, result["app"].(map[string]any)["timeout"])
assert.Equal(t, "defaultValue", result["defaultKey"])
assert.Equal(t, "localhost", result["database"].(map[string]interface{})["host"])
assert.Equal(t, 5432, result["database"].(map[string]interface{})["port"])
assert.Equal(t, "localhost", result["database"].(map[string]any)["host"])
assert.Equal(t, 5432, result["database"].(map[string]any)["port"])
}
func TestGetValues_Run_EmptyValues(t *testing.T) {
@ -156,7 +156,7 @@ func TestGetValues_Run_EmptyValues(t *testing.T) {
Version: "1.0.0",
},
},
Config: map[string]interface{}{},
Config: map[string]any{},
Version: 1,
Namespace: "default",
}
@ -165,7 +165,7 @@ func TestGetValues_Run_EmptyValues(t *testing.T) {
result, err := client.Run(releaseName)
require.NoError(t, err)
assert.Equal(t, map[string]interface{}{}, result)
assert.Equal(t, map[string]any{}, result)
}
func TestGetValues_Run_UnreachableKubeClient(t *testing.T) {

@ -19,6 +19,7 @@ package action
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"reflect"
@ -173,7 +174,7 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
t.Helper()
var expectedOutput string
if shouldOutput {
expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace)
expectedOutput = "attempted to output logs for namespace: " + expectedNamespace
}
is := assert.New(t)
instAction := installAction(t)
@ -186,7 +187,7 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
{Name: "templates/hello", ModTime: modTime, Data: []byte("hello: world")},
{Name: "templates/hooks", ModTime: modTime, Data: []byte(manifest)},
}
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.NoError(err)
@ -200,13 +201,13 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
t.Helper()
var expectedOutput string
if shouldOutput {
expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace)
expectedOutput = "attempted to output logs for namespace: " + expectedNamespace
}
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "failed-hooks"
failingClient := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failingClient.WatchUntilReadyError = fmt.Errorf("failed watch")
failingClient.WatchUntilReadyError = errors.New("failed watch")
instAction.cfg.KubeClient = failingClient
outBuffer := &bytes.Buffer{}
failingClient.PrintingKubeClient = kubefake.PrintingKubeClient{Out: io.Discard, LogOutput: outBuffer}
@ -216,7 +217,7 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
{Name: "templates/hello", ModTime: modTime, Data: []byte("hello: world")},
{Name: "templates/hooks", ModTime: modTime, Data: []byte(manifest)},
}
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.Error(err)

@ -182,7 +182,7 @@ func TestInstallRelease(t *testing.T) {
req := require.New(t)
instAction := installAction(t)
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, done := context.WithCancel(t.Context())
resi, err := instAction.RunWithContext(ctx, buildChart(), vals)
if err != nil {
@ -288,13 +288,13 @@ func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) {
func TestInstallReleaseWithValues(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
userVals := map[string]interface{}{
"nestedKey": map[string]interface{}{
userVals := map[string]any{
"nestedKey": map[string]any{
"simpleKey": "simpleValue",
},
}
expectedUserValues := map[string]interface{}{
"nestedKey": map[string]interface{}{
expectedUserValues := map[string]any{
"nestedKey": map[string]any{
"simpleKey": "simpleValue",
},
}
@ -328,7 +328,7 @@ func TestInstallReleaseWithValues(t *testing.T) {
func TestInstallRelease_NoName(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = ""
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
if err == nil {
t.Fatal("expected failure when no name is specified")
@ -340,7 +340,7 @@ func TestInstallRelease_WithNotes(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withNotes("note here")), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -371,7 +371,7 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withNotes("got-{{.Release.Name}}")), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -384,7 +384,7 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) {
rel, err := releaserToV1Release(r)
is.NoError(err)
expectedNotes := fmt.Sprintf("got-%s", res.Name)
expectedNotes := "got-" + res.Name
is.Equal(expectedNotes, rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete")
}
@ -394,7 +394,7 @@ func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withNotes("parent"), withDependency(withNotes("child"))), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -417,7 +417,7 @@ func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "with-notes"
instAction.SubNotes = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withNotes("parent"), withDependency(withNotes("child"))), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -443,7 +443,7 @@ func TestInstallRelease_DryRunClient(t *testing.T) {
instAction := installAction(t)
instAction.DryRunStrategy = dryRunStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withSampleTemplates()), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -505,7 +505,7 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
// First perform a normal dry-run with the secret and confirm its presence.
instAction.DryRunStrategy = DryRunClient
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(withSampleSecret(), withSampleTemplates()), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -520,7 +520,7 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
// Perform a dry-run where the secret should not be present
instAction.HideSecret = true
vals = map[string]interface{}{}
vals = map[string]any{}
res2i, err := instAction.Run(buildChart(withSampleSecret(), withSampleTemplates()), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -536,10 +536,10 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
// Ensure there is an error when HideSecret True but not in a dry-run mode
instAction.DryRunStrategy = DryRunNone
vals = map[string]interface{}{}
vals = map[string]any{}
_, err = instAction.Run(buildChart(withSampleSecret(), withSampleTemplates()), vals)
if err == nil {
t.Fatalf("Did not get expected an error when dry-run false and hide secret is true")
t.Fatal("Did not get the expected error when dry-run is false and hide secret is true")
}
}
@ -548,7 +548,7 @@ func TestInstallRelease_DryRun_Lookup(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.DryRunStrategy = DryRunNone
vals := map[string]interface{}{}
vals := map[string]any{}
mockChart := buildChart(withSampleTemplates())
mockChart.Templates = append(mockChart.Templates, &common.File{
@ -571,7 +571,7 @@ func TestInstallReleaseIncorrectTemplate_DryRun(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.DryRunStrategy = DryRunNone
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := instAction.Run(buildChart(withSampleIncludingIncorrectTemplates()), vals)
expectedErr := `hello/templates/incorrect:1:10
executing "hello/templates/incorrect" at <.Values.bad.doh>:
@ -589,7 +589,7 @@ func TestInstallRelease_NoHooks(t *testing.T) {
instAction.ReleaseName = "no-hooks"
require.NoError(t, instAction.cfg.Releases.Create(releaseStub()))
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
if err != nil {
t.Fatalf("Failed install: %s", err)
@ -605,12 +605,12 @@ func TestInstallRelease_FailedHooks(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "failed-hooks"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("Failed watch")
failer.WatchUntilReadyError = errors.New("Failed watch")
instAction.cfg.KubeClient = failer
outBuffer := &bytes.Buffer{}
failer.PrintingKubeClient = kubefake.PrintingKubeClient{Out: io.Discard, LogOutput: outBuffer}
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
res, err := releaserToV1Release(resi)
@ -630,7 +630,7 @@ func TestInstallRelease_ReplaceRelease(t *testing.T) {
require.NoError(t, instAction.cfg.Releases.Create(rel))
instAction.ReleaseName = rel.Name
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.NoError(err)
res, err := releaserToV1Release(resi)
@ -650,13 +650,13 @@ func TestInstallRelease_ReplaceRelease(t *testing.T) {
func TestInstallRelease_KubeVersion(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := instAction.Run(buildChart(withKube(">=0.0.0")), vals)
is.NoError(err)
// This should fail for a few hundred years
instAction.ReleaseName = "should-fail"
vals = map[string]interface{}{}
vals = map[string]any{}
_, err = instAction.Run(buildChart(withKube(">=99.0.0")), vals)
is.Error(err)
is.Contains(err.Error(), "chart requires kubeVersion: >=99.0.0 which is incompatible with Kubernetes v1.20.")
@ -667,10 +667,10 @@ func TestInstallRelease_Wait(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.WaitError = errors.New("I timed out")
instAction.cfg.KubeClient = failer
instAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
goroutines := instAction.getGoroutineCount()
@ -691,7 +691,7 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
failer.WaitDuration = 10 * time.Second
instAction.cfg.KubeClient = failer
instAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel)
@ -711,11 +711,11 @@ func TestInstallRelease_WaitForJobs(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.WaitError = errors.New("I timed out")
instAction.cfg.KubeClient = failer
instAction.WaitStrategy = kube.StatusWatcherStrategy
instAction.WaitForJobs = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
@ -732,13 +732,13 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.WaitError = errors.New("I timed out")
instAction.cfg.KubeClient = failer
instAction.RollbackOnFailure = true
// disabling hooks to avoid an early fail when
// WaitForDelete is called on the pre-delete hook execution
instAction.DisableHooks = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := instAction.Run(buildChart(), vals)
is.Error(err)
@ -757,11 +757,11 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away-with-me"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.DeleteError = fmt.Errorf("uninstall fail")
failer.WaitError = errors.New("I timed out")
failer.DeleteError = errors.New("uninstall fail")
instAction.cfg.KubeClient = failer
instAction.RollbackOnFailure = true
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
is.Error(err)
@ -779,7 +779,7 @@ func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
failer.WaitDuration = 10 * time.Second
instAction.cfg.KubeClient = failer
instAction.RollbackOnFailure = true
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel)
@ -875,7 +875,7 @@ func TestNameTemplate(t *testing.T) {
func TestInstallReleaseOutputDir(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
vals := map[string]interface{}{}
vals := map[string]any{}
dir := t.TempDir()
@ -907,7 +907,7 @@ func TestInstallReleaseOutputDir(t *testing.T) {
func TestInstallOutputDirWithReleaseName(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
vals := map[string]interface{}{}
vals := map[string]any{}
dir := t.TempDir()
@ -1324,7 +1324,7 @@ func TestInstallRelease_WaitOptionsPassedDownstream(t *testing.T) {
// Access the underlying FailingKubeClient to check recorded options
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := instAction.Run(buildChart(), vals)
is.NoError(err)

@ -53,7 +53,7 @@ func NewLint() *Lint {
}
// Run executes 'helm Lint' against the given chart.
func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
func (l *Lint) Run(paths []string, vals map[string]any) *LintResult {
lowestTolerance := support.ErrorSev
if l.Strict {
lowestTolerance = support.WarningSev
@ -87,7 +87,7 @@ func HasWarningsOrErrors(result *LintResult) bool {
return len(result.Errors) > 0
}
func lintChart(path string, vals map[string]interface{}, namespace string, kubeVersion *common.KubeVersion, skipSchemaValidation bool) (support.Linter, error) {
func lintChart(path string, vals map[string]any, namespace string, kubeVersion *common.KubeVersion, skipSchemaValidation bool) (support.Linter, error) {
var chartPath string
linter := support.Linter{}

@ -26,7 +26,7 @@ import (
)
var (
values = make(map[string]interface{})
values = make(map[string]any)
namespace = "testNamespace"
chart1MultipleChartLint = "testdata/charts/multiplecharts-lint-chart-1"
chart2MultipleChartLint = "testdata/charts/multiplecharts-lint-chart-2"
@ -88,7 +88,7 @@ func TestLintChart(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := lintChart(tt.chartPath, map[string]interface{}{}, namespace, nil, tt.skipSchemaValidation)
_, err := lintChart(tt.chartPath, map[string]any{}, namespace, nil, tt.skipSchemaValidation)
switch {
case err != nil && !tt.err:
t.Errorf("%s", err)

@ -70,7 +70,7 @@ func NewPackage() *Package {
}
// Run executes 'helm package' against the given chart and returns the path to the packaged chart.
func (p *Package) Run(path string, _ map[string]interface{}) (string, error) {
func (p *Package) Run(path string, _ map[string]any) (string, error) {
chrt, err := loader.LoadDir(path)
if err != nil {
return "", err

@ -43,7 +43,7 @@ func TestShow(t *testing.T) {
Raw: []*common.File{
{Name: "values.yaml", ModTime: modTime, Data: []byte("VALUES\n")},
},
Values: map[string]interface{}{},
Values: map[string]any{},
}
output, err := client.Run("")

@ -19,7 +19,6 @@ package action
import (
"context"
"errors"
"fmt"
"io"
"testing"
@ -115,7 +114,7 @@ func TestUninstallRelease_Wait(t *testing.T) {
}`
require.NoError(t, unAction.cfg.Releases.Create(rel))
failer := unAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitForDeleteError = fmt.Errorf("U timed out")
failer.WaitForDeleteError = errors.New("U timed out")
unAction.cfg.KubeClient = failer
resi, err := unAction.Run(rel.Name)
is.Error(err)
@ -149,7 +148,7 @@ func TestUninstallRelease_Cascade(t *testing.T) {
}`
require.NoError(t, unAction.cfg.Releases.Create(rel))
failer := unAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.DeleteError = fmt.Errorf("Uninstall with cascade failed")
failer.DeleteError = errors.New("Uninstall with cascade failed")
failer.BuildDummy = true
unAction.cfg.KubeClient = failer
_, err := unAction.Run(rel.Name)

@ -470,7 +470,7 @@ func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *rele
if !u.DisableHooks {
if err := u.cfg.execHook(upgradedRelease, release.HookPreUpgrade, u.WaitStrategy, u.WaitOptions, u.Timeout, serverSideApply); err != nil {
u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, fmt.Errorf("pre-upgrade hooks failed: %s", err))
u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, fmt.Errorf("pre-upgrade hooks failed: %w", err))
return
}
} else {
@ -518,7 +518,7 @@ func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *rele
// post-upgrade hooks
if !u.DisableHooks {
if err := u.cfg.execHook(upgradedRelease, release.HookPostUpgrade, u.WaitStrategy, u.WaitOptions, u.Timeout, serverSideApply); err != nil {
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, fmt.Errorf("post-upgrade hooks failed: %s", err))
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, fmt.Errorf("post-upgrade hooks failed: %w", err))
return
}
}

@ -60,7 +60,7 @@ func TestUpgradeRelease_Success(t *testing.T) {
req.NoError(upAction.cfg.Releases.Create(rel))
upAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, done := context.WithCancel(t.Context())
resi, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals)
@ -91,10 +91,10 @@ func TestUpgradeRelease_Wait(t *testing.T) {
require.NoError(t, upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.WaitError = errors.New("I timed out")
upAction.cfg.KubeClient = failer
upAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
@ -115,11 +115,11 @@ func TestUpgradeRelease_WaitForJobs(t *testing.T) {
require.NoError(t, upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.WaitError = errors.New("I timed out")
upAction.cfg.KubeClient = failer
upAction.WaitStrategy = kube.StatusWatcherStrategy
upAction.WaitForJobs = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
@ -140,12 +140,12 @@ func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
require.NoError(t, upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
failer.DeleteError = fmt.Errorf("I tried to delete nil")
failer.WaitError = errors.New("I timed out")
failer.DeleteError = errors.New("I tried to delete nil")
upAction.cfg.KubeClient = failer
upAction.WaitStrategy = kube.StatusWatcherStrategy
upAction.CleanupOnFail = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
@ -170,10 +170,10 @@ func TestUpgradeRelease_RollbackOnFailure(t *testing.T) {
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
// We can't make Update error because then the rollback won't work
failer.WatchUntilReadyError = fmt.Errorf("arming key removed")
failer.WatchUntilReadyError = errors.New("arming key removed")
upAction.cfg.KubeClient = failer
upAction.RollbackOnFailure = true
vals := map[string]interface{}{}
vals := map[string]any{}
resi, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
@ -199,10 +199,10 @@ func TestUpgradeRelease_RollbackOnFailure(t *testing.T) {
require.NoError(t, upAction.cfg.Releases.Create(rel))
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.UpdateError = fmt.Errorf("update fail")
failer.UpdateError = errors.New("update fail")
upAction.cfg.KubeClient = failer
upAction.RollbackOnFailure = true
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
@ -217,17 +217,17 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
t.Run("reuse values should work with values", func(t *testing.T) {
upAction := upgradeAction(t)
existingValues := map[string]interface{}{
existingValues := map[string]any{
"name": "value",
"maxHeapSize": "128m",
"replicas": 2,
}
newValues := map[string]interface{}{
newValues := map[string]any{
"name": "newValue",
"maxHeapSize": "512m",
"cpu": "12m",
}
expectedValues := map[string]interface{}{
expectedValues := map[string]any{
"name": "newValue",
"maxHeapSize": "512m",
"cpu": "12m",
@ -266,8 +266,8 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
t.Run("reuse values should not install disabled charts", func(t *testing.T) {
upAction := upgradeAction(t)
chartDefaultValues := map[string]interface{}{
"subchart": map[string]interface{}{
chartDefaultValues := map[string]any{
"subchart": map[string]any{
"enabled": true,
},
}
@ -283,8 +283,8 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
withMetadataDependency(dependency),
)
now := time.Now()
existingValues := map[string]interface{}{
"subchart": map[string]interface{}{
existingValues := map[string]any{
"subchart": map[string]any{
"enabled": false,
},
}
@ -311,7 +311,7 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
withMetadataDependency(dependency),
)
// reusing values and upgrading
resi, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]interface{}{})
resi, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]any{})
is.NoError(err)
res, err := releaserToV1Release(resi)
is.NoError(err)
@ -330,8 +330,8 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
is.Equal(common.StatusDeployed, updatedRes.Info.Status)
is.Equal(0, len(updatedRes.Chart.Dependencies()), "expected 0 dependencies")
expectedValues := map[string]interface{}{
"subchart": map[string]interface{}{
expectedValues := map[string]any{
"subchart": map[string]any{
"enabled": false,
},
}
@ -345,20 +345,20 @@ func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) {
t.Run("reset then reuse values should work with values", func(t *testing.T) {
upAction := upgradeAction(t)
existingValues := map[string]interface{}{
existingValues := map[string]any{
"name": "value",
"maxHeapSize": "128m",
"replicas": 2,
}
newValues := map[string]interface{}{
newValues := map[string]any{
"name": "newValue",
"maxHeapSize": "512m",
"cpu": "12m",
}
newChartValues := map[string]interface{}{
newChartValues := map[string]any{
"memory": "256m",
}
expectedValues := map[string]interface{}{
expectedValues := map[string]any{
"name": "newValue",
"maxHeapSize": "512m",
"cpu": "12m",
@ -411,7 +411,7 @@ func TestUpgradeRelease_Pending(t *testing.T) {
rel2.Version = 2
require.NoError(t, upAction.cfg.Releases.Create(rel2))
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := upAction.Run(rel.Name, buildChart(), vals)
req.Contains(err.Error(), "progress", err)
@ -431,7 +431,7 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
failer.WaitDuration = 10 * time.Second
upAction.cfg.KubeClient = failer
upAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel)
@ -460,7 +460,7 @@ func TestUpgradeRelease_Interrupted_RollbackOnFailure(t *testing.T) {
failer.WaitDuration = 5 * time.Second
upAction.cfg.KubeClient = failer
upAction.RollbackOnFailure = true
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel)
@ -590,7 +590,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
req.NoError(upAction.cfg.Releases.Create(rel))
upAction.DryRunStrategy = DryRunClient
vals := map[string]interface{}{}
vals := map[string]any{}
ctx, done := context.WithCancel(t.Context())
resi, err := upAction.RunWithContext(ctx, rel.Name, buildChart(withSampleSecret()), vals)
@ -610,7 +610,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
// Test the case for hiding the secret to ensure it is not displayed
upAction.HideSecret = true
vals = map[string]interface{}{}
vals = map[string]any{}
ctx, done = context.WithCancel(t.Context())
resi, err = upAction.RunWithContext(ctx, rel.Name, buildChart(withSampleSecret()), vals)
@ -630,7 +630,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
// Ensure in a dry run mode when using HideSecret
upAction.DryRunStrategy = DryRunNone
vals = map[string]interface{}{}
vals = map[string]any{}
ctx, done = context.WithCancel(t.Context())
_, err = upAction.RunWithContext(ctx, rel.Name, buildChart(withSampleSecret()), vals)
@ -801,7 +801,7 @@ func TestUpgradeRun_UnreachableKubeClient(t *testing.T) {
config.KubeClient = &failingKubeClient
client := NewUpgrade(config)
vals := map[string]interface{}{}
vals := map[string]any{}
result, err := client.Run("", buildChart(), vals)
assert.Nil(t, result)
@ -844,7 +844,7 @@ func TestUpgradeRelease_WaitOptionsPassedDownstream(t *testing.T) {
// Access the underlying FailingKubeClient to check recorded options
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
vals := map[string]interface{}{}
vals := map[string]any{}
_, err := upAction.Run(rel.Name, buildChart(), vals)
req.NoError(err)

@ -173,8 +173,8 @@ func newCapabilities(kubeVersionMajor, kubeVersionMinor uint64) (*Capabilities,
KubeVersion: KubeVersion{
Version: version,
normalizedVersion: version,
Major: fmt.Sprintf("%d", kubeVersionMajor),
Minor: fmt.Sprintf("%d", kubeVersionMinor),
Major: strconv.FormatUint(kubeVersionMajor, 10),
Minor: strconv.FormatUint(kubeVersionMinor, 10),
},
APIVersions: DefaultVersionSet,
HelmVersion: helmversion.Get(),

@ -73,7 +73,7 @@ func newHTTPURLLoader() *HTTPURLLoader {
}
// ValidateAgainstSchema checks that values does not violate the structure laid out in schema
func ValidateAgainstSchema(ch chart.Charter, values map[string]interface{}) error {
func ValidateAgainstSchema(ch chart.Charter, values map[string]any) error {
chrt, err := chart.NewAccessor(ch)
if err != nil {
return err

@ -54,7 +54,7 @@ func TestValidateAgainstInvalidSingleSchema(t *testing.T) {
var errString string
if err := ValidateAgainstSingleSchema(values, schema); err == nil {
t.Fatalf("Expected an error, but got nil")
t.Fatal("Expected an error, but got nil")
} else {
errString = err.Error()
}
@ -78,7 +78,7 @@ func TestValidateAgainstSingleSchemaNegative(t *testing.T) {
var errString string
if err := ValidateAgainstSingleSchema(values, schema); err == nil {
t.Fatalf("Expected an error, but got nil")
t.Fatal("Expected an error, but got nil")
} else {
errString = err.Error()
}
@ -172,7 +172,7 @@ func TestValidateAgainstSchemaNegative(t *testing.T) {
var errString string
if err := ValidateAgainstSchema(chrt, vals); err == nil {
t.Fatalf("Expected an error, but got nil")
t.Fatal("Expected an error, but got nil")
} else {
errString = err.Error()
}
@ -236,7 +236,7 @@ func TestValidateAgainstSchema2020Negative(t *testing.T) {
var errString string
if err := ValidateAgainstSchema(chrt, vals); err == nil {
t.Fatalf("Expected an error, but got nil")
t.Fatal("Expected an error, but got nil")
} else {
errString = err.Error()
}
@ -386,6 +386,6 @@ func TestValidateAgainstSchema_InvalidSubchartValuesType_NoPanic(t *testing.T) {
// We expect a non-nil error (invalid type), but crucially no panic.
if err := ValidateAgainstSchema(chrt, vals); err == nil {
t.Fatalf("expected an error when subchart values have invalid type, got nil")
t.Fatal("expected an error when subchart values have invalid type, got nil")
}
}

@ -29,7 +29,7 @@ import (
const GlobalKey = "global"
// Values represents a collection of chart values.
type Values map[string]interface{}
type Values map[string]any
// YAML encodes the Values into a YAML string.
func (v Values) YAML() (string, error) {
@ -64,9 +64,9 @@ func (v Values) Table(name string) (Values, error) {
// AsMap is a utility function for converting Values to a map[string]interface{}.
//
// It protects against nil map panics.
func (v Values) AsMap() map[string]interface{} {
func (v Values) AsMap() map[string]any {
if len(v) == 0 {
return map[string]interface{}{}
return map[string]any{}
}
return v
}
@ -86,7 +86,7 @@ func tableLookup(v Values, simple string) (Values, error) {
if !ok {
return v, ErrNoTable{simple}
}
if vv, ok := v2.(map[string]interface{}); ok {
if vv, ok := v2.(map[string]any); ok {
return vv, nil
}
@ -113,7 +113,7 @@ func ReadValues(data []byte) (vals Values, err error) {
func ReadValuesFile(filename string) (Values, error) {
data, err := os.ReadFile(filename)
if err != nil {
return map[string]interface{}{}, err
return map[string]any{}, err
}
return ReadValues(data)
}
@ -129,8 +129,8 @@ type ReleaseOptions struct {
}
// istable is a special-purpose function to see if the present thing matches the definition of a YAML table.
func istable(v interface{}) bool {
_, ok := v.(map[string]interface{})
func istable(v any) bool {
_, ok := v.(map[string]any)
return ok
}
@ -141,14 +141,14 @@ func istable(v interface{}) bool {
// chapter:
// one:
// title: "Loomings"
func (v Values) PathValue(path string) (interface{}, error) {
func (v Values) PathValue(path string) (any, error) {
if path == "" {
return nil, errors.New("YAML path cannot be empty")
}
return v.pathValue(parsePath(path))
}
func (v Values) pathValue(path []string) (interface{}, error) {
func (v Values) pathValue(path []string) (any, error) {
if len(path) == 1 {
// if exists must be root key not table
if _, ok := v[path[0]]; ok && !istable(v[path[0]]) {

@ -135,7 +135,7 @@ chapter:
}
}
func matchValues(t *testing.T, data map[string]interface{}) {
func matchValues(t *testing.T, data map[string]any) {
t.Helper()
if data["poet"] != "Coleridge" {
t.Errorf("Unexpected poet: %s", data["poet"])
@ -160,7 +160,7 @@ func matchValues(t *testing.T, data map[string]interface{}) {
}
}
func ttpl(tpl string, v map[string]interface{}) (string, error) {
func ttpl(tpl string, v map[string]any) (string, error) {
var b bytes.Buffer
tt := template.Must(template.New("t").Parse(tpl))
err := tt.Execute(&b, v)

@ -48,11 +48,11 @@ type Chart struct {
// Templates for this chart.
Templates []*common.File `json:"templates"`
// Values are default config for this chart.
Values map[string]interface{} `json:"values"`
Values map[string]any `json:"values"`
// Schema is an optional JSON schema for imposing structure on Values
Schema []byte `json:"schema"`
// SchemaModTime the schema was last modified
SchemaModTime time.Time `json:"schemamodtime,omitempty"`
SchemaModTime time.Time `json:"schemamodtime"`
// Files are miscellaneous files in a chart archive,
// e.g. README, LICENSE, etc.
Files []*common.File `json:"files"`

@ -44,7 +44,7 @@ type Dependency struct {
Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
// ImportValues holds the mapping of source values to parent key to be imported. Each item can be a
// string or pair of child/parent sublist items.
ImportValues []interface{} `json:"import-values,omitempty" yaml:"import-values,omitempty"`
ImportValues []any `json:"import-values,omitempty" yaml:"import-values,omitempty"`
// Alias usable alias to be used for the chart
Alias string `json:"alias,omitempty" yaml:"alias,omitempty"`
}

@ -25,6 +25,6 @@ func (v ValidationError) Error() string {
}
// ValidationErrorf takes a message and formatting options and creates a ValidationError
func ValidationErrorf(msg string, args ...interface{}) ValidationError {
func ValidationErrorf(msg string, args ...any) ValidationError {
return ValidationError(fmt.Sprintf(msg, args...))
}

@ -43,7 +43,7 @@ func WithSkipSchemaValidation(skipSchemaValidation bool) LinterOption {
}
}
func RunAll(baseDir string, values map[string]interface{}, namespace string, options ...LinterOption) support.Linter {
func RunAll(baseDir string, values map[string]any, namespace string, options ...LinterOption) support.Linter {
chartDir, _ := filepath.Abs(baseDir)

@ -235,7 +235,7 @@ func TestMalformedTemplate(t *testing.T) {
}()
select {
case <-c:
t.Fatalf("lint malformed template timeout")
t.Fatal("lint malformed template timeout")
case <-ch:
if len(m) != 1 {
t.Fatalf("All didn't fail with expected errors, got %#v", m)

@ -19,7 +19,6 @@ package rules
import (
"bytes"
"errors"
"fmt"
"io"
"io/fs"
"os"
@ -102,14 +101,14 @@ func validateCrdsDir(crdsPath string) error {
func validateCrdAPIVersion(obj *k8sYamlStruct) error {
if !strings.HasPrefix(obj.APIVersion, "apiextensions.k8s.io") {
return fmt.Errorf("apiVersion is not in 'apiextensions.k8s.io'")
return errors.New("apiVersion is not in 'apiextensions.k8s.io'")
}
return nil
}
func validateCrdKind(obj *k8sYamlStruct) error {
if obj.Kind != "CustomResourceDefinition" {
return fmt.Errorf("object kind is not 'CustomResourceDefinition'")
return errors.New("object kind is not 'CustomResourceDefinition'")
}
return nil
}

@ -49,7 +49,7 @@ func TestValidateAllowedExtension(t *testing.T) {
}
}
var values = map[string]interface{}{"nameOverride": "", "httpPort": 80}
var values = map[string]any{"nameOverride": "", "httpPort": 80}
const namespace = "testNamespace"
@ -264,7 +264,7 @@ func TestStrictTemplateParsingMapError(t *testing.T) {
APIVersion: "v2",
Version: "0.1.0",
},
Values: map[string]interface{}{
Values: map[string]any{
"mymap": map[string]string{
"key1": "val1",
},

@ -508,7 +508,7 @@ func TestLoadInvalidArchive(t *testing.T) {
func TestLoadValues(t *testing.T) {
testCases := map[string]struct {
data []byte
expctedValues map[string]interface{}
expctedValues map[string]any
}{
"It should load values correctly": {
data: []byte(`
@ -517,11 +517,11 @@ foo:
bar:
version: v2
`),
expctedValues: map[string]interface{}{
"foo": map[string]interface{}{
expctedValues: map[string]any{
"foo": map[string]any{
"image": "foo:v1",
},
"bar": map[string]interface{}{
"bar": map[string]any{
"version": "v2",
},
},
@ -536,11 +536,11 @@ bar:
foo:
image: foo:v2
`),
expctedValues: map[string]interface{}{
"foo": map[string]interface{}{
expctedValues: map[string]any{
"foo": map[string]any{
"image": "foo:v2",
},
"bar": map[string]interface{}{
"bar": map[string]any{
"version": "v2",
},
},
@ -560,24 +560,24 @@ foo:
}
func TestMergeValuesV2(t *testing.T) {
nestedMap := map[string]interface{}{
nestedMap := map[string]any{
"foo": "bar",
"baz": map[string]string{
"cool": "stuff",
},
}
anotherNestedMap := map[string]interface{}{
anotherNestedMap := map[string]any{
"foo": "bar",
"baz": map[string]string{
"cool": "things",
"awesome": "stuff",
},
}
flatMap := map[string]interface{}{
flatMap := map[string]any{
"foo": "bar",
"baz": "stuff",
}
anotherFlatMap := map[string]interface{}{
anotherFlatMap := map[string]any{
"testing": "fun",
}
@ -600,7 +600,7 @@ func TestMergeValuesV2(t *testing.T) {
}
testMap = MergeMaps(anotherFlatMap, anotherNestedMap)
expectedMap := map[string]interface{}{
expectedMap := map[string]any{
"testing": "fun",
"foo": "bar",
"baz": map[string]string{

@ -16,6 +16,7 @@ limitations under the License.
package v2
import (
"errors"
"testing"
)
@ -181,7 +182,7 @@ func TestValidate(t *testing.T) {
for _, tt := range tests {
result := tt.md.Validate()
if result != tt.err {
if !errors.Is(result, tt.err) {
t.Errorf("expected %q, got %q in test %q", tt.err, result, tt.name)
}
}

@ -35,11 +35,11 @@ func TestLoadChartfile(t *testing.T) {
func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
t.Helper()
if f == nil { //nolint:staticcheck
if f == nil {
t.Fatal("Failed verifyChartfile because f is nil")
}
if f.APIVersion != chart.APIVersionV1 { //nolint:staticcheck
if f.APIVersion != chart.APIVersionV1 {
t.Errorf("Expected API Version %q, got %q", chart.APIVersionV1, f.APIVersion)
}
@ -68,7 +68,7 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
}
if len(f.Sources) != 1 {
t.Fatalf("Unexpected number of sources")
t.Fatal("Unexpected number of sources")
}
if f.Sources[0] != "https://example.com/foo/bar" {
@ -88,7 +88,7 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
}
if len(f.Annotations) != 2 {
t.Fatalf("Unexpected annotations")
t.Fatal("Unexpected annotations")
}
if want, got := "extravalue", f.Annotations["extrakey"]; want != got {

@ -142,7 +142,7 @@ func copyMetadata(metadata *chart.Metadata) *chart.Metadata {
}
// processDependencyEnabled removes disabled charts from dependencies
func processDependencyEnabled(c *chart.Chart, v map[string]interface{}, path string) error {
func processDependencyEnabled(c *chart.Chart, v map[string]any, path string) error {
if c.Metadata.Dependencies == nil {
return nil
}
@ -228,7 +228,7 @@ Loop:
}
// pathToMap creates a nested map given a YAML path in dot notation.
func pathToMap(path string, data map[string]interface{}) map[string]interface{} {
func pathToMap(path string, data map[string]any) map[string]any {
if path == "." {
return data
}
@ -237,13 +237,13 @@ func pathToMap(path string, data map[string]interface{}) map[string]interface{}
func parsePath(key string) []string { return strings.Split(key, ".") }
func set(path []string, data map[string]interface{}) map[string]interface{} {
func set(path []string, data map[string]any) map[string]any {
if len(path) == 0 {
return nil
}
cur := data
for i := len(path) - 1; i >= 0; i-- {
cur = map[string]interface{}{path[i]: cur}
cur = map[string]any{path[i]: cur}
}
return cur
}
@ -264,13 +264,13 @@ func processImportValues(c *chart.Chart, merge bool) error {
if err != nil {
return err
}
b := make(map[string]interface{})
b := make(map[string]any)
// import values from each dependency if specified in import-values
for _, r := range c.Metadata.Dependencies {
var outiv []interface{}
var outiv []any
for _, riv := range r.ImportValues {
switch iv := riv.(type) {
case map[string]interface{}:
case map[string]any:
child := fmt.Sprintf("%v", iv["child"])
parent := fmt.Sprintf("%v", iv["parent"])
@ -337,27 +337,27 @@ func processImportValues(c *chart.Chart, merge bool) error {
return nil
}
func deepCopyMap(vals map[string]interface{}) map[string]interface{} {
func deepCopyMap(vals map[string]any) map[string]any {
valsCopy, err := copystructure.Copy(vals)
if err != nil {
return vals
}
return valsCopy.(map[string]interface{})
return valsCopy.(map[string]any)
}
func trimNilValues(vals map[string]interface{}) map[string]interface{} {
func trimNilValues(vals map[string]any) map[string]any {
valsCopy, err := copystructure.Copy(vals)
if err != nil {
return vals
}
valsCopyMap := valsCopy.(map[string]interface{})
valsCopyMap := valsCopy.(map[string]any)
for key, val := range valsCopyMap {
if val == nil {
// Iterate over the values and remove nil keys
delete(valsCopyMap, key)
} else if istable(val) {
// Recursively call into ourselves to remove keys from inner tables
valsCopyMap[key] = trimNilValues(val.(map[string]interface{}))
valsCopyMap[key] = trimNilValues(val.(map[string]any))
}
}
@ -365,8 +365,8 @@ func trimNilValues(vals map[string]interface{}) map[string]interface{} {
}
// istable is a special-purpose function to see if the present thing matches the definition of a YAML table.
func istable(v interface{}) bool {
_, ok := v.(map[string]interface{})
func istable(v any) bool {
_, ok := v.(map[string]any)
return ok
}

@ -63,7 +63,7 @@ func TestLoadDependency(t *testing.T) {
}
func TestDependencyEnabled(t *testing.T) {
type M = map[string]interface{}
type M = map[string]any
tests := []struct {
name string
v M
@ -385,7 +385,7 @@ func TestGetAliasDependency(t *testing.T) {
req := c.Metadata.Dependencies
if len(req) == 0 {
t.Fatalf("there are no dependencies to test")
t.Fatal("there are no dependencies to test")
}
// Success case
@ -403,7 +403,7 @@ func TestGetAliasDependency(t *testing.T) {
if req[0].Version != "" {
if !IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
t.Fatalf("dependency chart version is not in the compatible range")
t.Fatal("dependency chart version is not in the compatible range")
}
}
@ -415,7 +415,7 @@ func TestGetAliasDependency(t *testing.T) {
req[0].Version = "something else which is not in the compatible range"
if IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
t.Fatalf("dependency chart version which is not in the compatible range should cause a failure other than a success ")
t.Fatal("dependency chart version outside the compatible range should fail, but it succeeded")
}
}

@ -21,8 +21,8 @@ import (
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path"
@ -90,7 +90,7 @@ func TestSave(t *testing.T) {
t.Fatalf("Schema data did not match.\nExpected:\n%s\nActual:\n%s", formattedExpected, formattedActual)
}
if _, err := Save(&chartWithInvalidJSON, dest); err == nil {
t.Fatalf("Invalid JSON was not caught while saving chart")
t.Fatal("Invalid JSON was not caught while saving chart")
}
c.Metadata.APIVersion = chart.APIVersionV2
@ -157,7 +157,7 @@ func TestSavePreservesTimestamps(t *testing.T) {
Version: "1.2.3",
},
ModTime: initialCreateTime,
Values: map[string]interface{}{
Values: map[string]any{
"imageName": "testimage",
"imageId": 42,
},
@ -357,5 +357,5 @@ func sha256Sum(filePath string) (string, error) {
return "", err
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
return hex.EncodeToString(h.Sum(nil)), nil
}

@ -102,7 +102,7 @@ type Writer interface {
// EncodeJSON is a helper function to decorate any error message with a bit more
// context and avoid writing the same code over and over for printers.
func EncodeJSON(out io.Writer, obj interface{}) error {
func EncodeJSON(out io.Writer, obj any) error {
enc := json.NewEncoder(out)
err := enc.Encode(obj)
if err != nil {
@ -113,7 +113,7 @@ func EncodeJSON(out io.Writer, obj interface{}) error {
// EncodeYAML is a helper function to decorate any error message with a bit more
// context and avoid writing the same code over and over for printers
func EncodeYAML(out io.Writer, obj interface{}) error {
func EncodeYAML(out io.Writer, obj any) error {
raw, err := yaml.Marshal(obj)
if err != nil {
return fmt.Errorf("unable to write YAML output: %w", err)

@ -298,7 +298,7 @@ func TestMergeValuesCLI(t *testing.T) {
tests := []struct {
name string
opts Options
expected map[string]interface{}
expected map[string]any
wantErr bool
}{
{
@ -306,8 +306,8 @@ func TestMergeValuesCLI(t *testing.T) {
opts: Options{
JSONValues: []string{`{"foo": {"bar": "baz"}}`},
},
expected: map[string]interface{}{
"foo": map[string]interface{}{
expected: map[string]any{
"foo": map[string]any{
"bar": "baz",
},
},
@ -317,9 +317,9 @@ func TestMergeValuesCLI(t *testing.T) {
opts: Options{
JSONValues: []string{"foo.bar=[1,2,3]"},
},
expected: map[string]interface{}{
"foo": map[string]interface{}{
"bar": []interface{}{1.0, 2.0, 3.0},
expected: map[string]any{
"foo": map[string]any{
"bar": []any{1.0, 2.0, 3.0},
},
},
},
@ -328,7 +328,7 @@ func TestMergeValuesCLI(t *testing.T) {
opts: Options{
Values: []string{"foo=bar"},
},
expected: map[string]interface{}{
expected: map[string]any{
"foo": "bar",
},
},
@ -337,7 +337,7 @@ func TestMergeValuesCLI(t *testing.T) {
opts: Options{
StringValues: []string{"foo=123"},
},
expected: map[string]interface{}{
expected: map[string]any{
"foo": "123",
},
},
@ -346,7 +346,7 @@ func TestMergeValuesCLI(t *testing.T) {
opts: Options{
LiteralValues: []string{"foo=true"},
},
expected: map[string]interface{}{
expected: map[string]any{
"foo": "true",
},
},
@ -358,7 +358,7 @@ func TestMergeValuesCLI(t *testing.T) {
JSONValues: []string{`{"c": "foo1"}`},
LiteralValues: []string{"d=bar1"},
},
expected: map[string]interface{}{
expected: map[string]any{
"a": "foo",
"b": "bar",
"c": "foo1",

@ -17,9 +17,9 @@ limitations under the License.
package cmd
import (
"fmt"
"os"
"path/filepath"
"slices"
"testing"
chartv3 "helm.sh/helm/v4/internal/chart/v3"
@ -47,7 +47,7 @@ func TestCreateCmd(t *testing.T) {
if fi, err := os.Stat(cname); err != nil {
t.Fatalf("no chart directory: %s", err)
} else if !fi.IsDir() {
t.Fatalf("chart is not directory")
t.Fatal("chart is not directory")
}
c, err := chartloader.LoadDir(cname)
@ -138,11 +138,11 @@ func TestCreateStarterCmd(t *testing.T) {
if tt.useAbsolutePath {
starterArg = filepath.Join(starterchart, "starterchart")
}
cmd := fmt.Sprintf("create --starter=%s", starterArg)
cmd := "create --starter=" + starterArg
if tt.chartAPIVersion == "v3" {
cmd += fmt.Sprintf(" --chart-api-version=%s", chartv3.APIVersionV3)
cmd += " --chart-api-version=" + chartv3.APIVersionV3
} else {
cmd += fmt.Sprintf(" --chart-api-version=%s", chartv2.APIVersionV2)
cmd += " --chart-api-version=" + chartv2.APIVersionV2
}
cmd += " " + cname
@ -155,7 +155,7 @@ func TestCreateStarterCmd(t *testing.T) {
if fi, err := os.Stat(cname); err != nil {
t.Fatalf("no chart directory: %s", err)
} else if !fi.IsDir() {
t.Fatalf("chart is not directory")
t.Fatal("chart is not directory")
}
// Load and verify the chart
@ -188,13 +188,7 @@ func TestCreateStarterCmd(t *testing.T) {
}
// Verify custom template exists
found := false
for _, name := range templates {
if name == "templates/foo.tpl" {
found = true
break
}
}
found := slices.Contains(templates, "templates/foo.tpl")
if !found {
t.Error("Did not find foo.tpl")
}
@ -221,7 +215,7 @@ func TestCreateCmdChartAPIVersionV2(t *testing.T) {
if fi, err := os.Stat(cname); err != nil {
t.Fatalf("no chart directory: %s", err)
} else if !fi.IsDir() {
t.Fatalf("chart is not directory")
t.Fatal("chart is not directory")
}
c, err := chartloader.LoadDir(cname)
@ -262,7 +256,7 @@ func TestCreateCmdChartAPIVersionV3(t *testing.T) {
if fi, err := os.Stat(cname); err != nil {
t.Fatalf("no chart directory: %s", err)
} else if !fi.IsDir() {
t.Fatalf("chart is not directory")
t.Fatal("chart is not directory")
}
c, err := chartloader.LoadDir(cname)

@ -208,7 +208,7 @@ func TestDependencyUpdateCmd_DoNotDeleteOldChartsOnError(t *testing.T) {
// Make sure tmpcharts-x is deleted
tmpPath := filepath.Join(dir(chartname), fmt.Sprintf("tmpcharts-%d", os.Getpid()))
if _, err := os.Stat(tmpPath); !errors.Is(err, fs.ErrNotExist) {
t.Fatalf("tmpcharts dir still exists")
t.Fatal("tmpcharts dir still exists")
}
}

@ -17,6 +17,7 @@ limitations under the License.
package cmd
import (
"errors"
"flag"
"fmt"
"log"
@ -119,7 +120,7 @@ func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
// value to the given format pointer
func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) {
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(), ", ")))
"prints the output in the specified format. Allowed values: "+strings.Join(output.Formats(), ", "))
err := cmd.RegisterFlagCompletionFunc(outputFlag, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
var formatNames []string
@ -195,7 +196,7 @@ func (p *postRendererString) Set(val string) error {
return nil
}
if p.options.pluginName != "" {
return fmt.Errorf("cannot specify --post-renderer flag more than once")
return errors.New("cannot specify --post-renderer flag more than once")
}
p.options.pluginName = val
pr, err := postrenderer.NewPostRendererPlugin(p.options.settings, p.options.pluginName, p.options.args...)

@ -53,7 +53,7 @@ func newGetAllCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return err
}
if template != "" {
data := map[string]interface{}{
data := map[string]any{
"Release": res,
}
return tpl(template, data, out)

@ -33,7 +33,7 @@ This command downloads a values file for a given release.
`
type valuesWriter struct {
vals map[string]interface{}
vals map[string]any
allValues bool
}

@ -106,7 +106,7 @@ type releaseInfoJSON struct {
// It handles empty string time fields by treating them as zero values.
func (r *releaseInfo) UnmarshalJSON(data []byte) error {
// First try to unmarshal into a map to handle empty string time fields
var raw map[string]interface{}
var raw map[string]any
if err := json.Unmarshal(data, &raw); err != nil {
return err
}

@ -321,7 +321,7 @@ func TestReleaseInfoEmptyStringRoundTrip(t *testing.T) {
data, err := json.Marshal(&info)
require.NoError(t, err)
var result map[string]interface{}
var result map[string]any
err = json.Unmarshal(data, &result)
require.NoError(t, err)

@ -201,6 +201,7 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal
f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "update dependencies if they are missing before installing the chart")
f.BoolVar(&client.DisableOpenAPIValidation, "disable-openapi-validation", false, "if set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema")
f.BoolVar(&client.RollbackOnFailure, "rollback-on-failure", false, "if set, Helm will rollback (uninstall) the installation upon failure. The --wait flag will be default to \"watcher\" if --rollback-on-failure is set")
f.BoolVar(&client.RollbackOnFailure, "atomic", false, "deprecated")
f.MarkDeprecated("atomic", "use --rollback-on-failure instead")
f.BoolVar(&client.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed. By default, CRDs are installed if not already present")
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")

@ -291,27 +291,27 @@ func TestInstallVersionCompletion(t *testing.T) {
tests := []cmdTestCase{{
name: "completion for install version flag with release name",
cmd: fmt.Sprintf("%s __complete install releasename testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete install releasename testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for install version flag with generate-name",
cmd: fmt.Sprintf("%s __complete install --generate-name testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete install --generate-name testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for install version flag, no filter",
cmd: fmt.Sprintf("%s __complete install releasename testing/alpine --version 0.3", repoSetup),
cmd: repoSetup + " __complete install releasename testing/alpine --version 0.3",
golden: "output/version-comp.txt",
}, {
name: "completion for install version flag too few args",
cmd: fmt.Sprintf("%s __complete install testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete install testing/alpine --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for install version flag too many args",
cmd: fmt.Sprintf("%s __complete install releasename testing/alpine badarg --version ''", repoSetup),
cmd: repoSetup + " __complete install releasename testing/alpine badarg --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for install version flag invalid chart",
cmd: fmt.Sprintf("%s __complete install releasename invalid/invalid --version ''", repoSetup),
cmd: repoSetup + " __complete install releasename invalid/invalid --version ''",
golden: "output/version-invalid-comp.txt",
}}
runTestCmd(t, tests)

@ -25,12 +25,12 @@ func TestLintCmdWithSubchartsFlag(t *testing.T) {
testChart := "testdata/testcharts/chart-with-bad-subcharts"
tests := []cmdTestCase{{
name: "lint good chart with bad subcharts",
cmd: fmt.Sprintf("lint %s", testChart),
cmd: "lint " + testChart,
golden: "output/lint-chart-with-bad-subcharts.txt",
wantError: true,
}, {
name: "lint good chart with bad subcharts using --with-subcharts flag",
cmd: fmt.Sprintf("lint --with-subcharts %s", testChart),
cmd: "lint --with-subcharts " + testChart,
golden: "output/lint-chart-with-bad-subcharts-with-subcharts.txt",
wantError: true,
}}
@ -42,7 +42,7 @@ func TestLintCmdWithQuietFlag(t *testing.T) {
testChart2 := "testdata/testcharts/chart-bad-requirements"
tests := []cmdTestCase{{
name: "lint good chart using --quiet flag",
cmd: fmt.Sprintf("lint --quiet %s", testChart1),
cmd: "lint --quiet " + testChart1,
golden: "output/lint-quiet.txt",
}, {
name: "lint two charts, one with error using --quiet flag",
@ -67,24 +67,24 @@ func TestLintCmdWithKubeVersionFlag(t *testing.T) {
testChart := "testdata/testcharts/chart-with-deprecated-api"
tests := []cmdTestCase{{
name: "lint chart with deprecated api version using kube version flag",
cmd: fmt.Sprintf("lint --kube-version 1.22.0 %s", testChart),
cmd: "lint --kube-version 1.22.0 " + testChart,
golden: "output/lint-chart-with-deprecated-api.txt",
wantError: false,
}, {
name: "lint chart with deprecated api version using kube version and strict flag",
cmd: fmt.Sprintf("lint --kube-version 1.22.0 --strict %s", testChart),
cmd: "lint --kube-version 1.22.0 --strict " + testChart,
golden: "output/lint-chart-with-deprecated-api-strict.txt",
wantError: true,
}, {
// the test builds will use the kubeVersionMinorTesting const in capabilities.go
// which is "20"
name: "lint chart with deprecated api version without kube version",
cmd: fmt.Sprintf("lint %s", testChart),
cmd: "lint " + testChart,
golden: "output/lint-chart-with-deprecated-api-old-k8s.txt",
wantError: false,
}, {
name: "lint chart with deprecated api version with older kube version",
cmd: fmt.Sprintf("lint --kube-version 1.21.0 --strict %s", testChart),
cmd: "lint --kube-version 1.21.0 --strict " + testChart,
golden: "output/lint-chart-with-deprecated-api-old-k8s.txt",
wantError: false,
}}

@ -16,6 +16,7 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"log/slog"
@ -102,7 +103,7 @@ func (o *pluginInstallOptions) complete(args []string) error {
func (o *pluginInstallOptions) newInstallerForSource() (installer.Installer, error) {
// Check if source is an OCI registry reference
if strings.HasPrefix(o.source, fmt.Sprintf("%s://", registry.OCIScheme)) {
if strings.HasPrefix(o.source, registry.OCIScheme+"://") {
// Build getter options for OCI
options := []getter.Option{
getter.WithTLSClientConfig(o.certFile, o.keyFile, o.caFile),
@ -135,7 +136,7 @@ func (o *pluginInstallOptions) run(out io.Writer) error {
} else if shouldVerify {
// For remote installations, check if verification is supported
if verifier, ok := i.(installer.Verifier); !ok || !verifier.SupportsVerification() {
return fmt.Errorf("plugin source does not support verification. Use --verify=false to skip verification")
return errors.New("plugin source does not support verification. Use --verify=false to skip verification")
}
} else {
// User explicitly disabled verification

@ -16,6 +16,7 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"os"
@ -75,12 +76,12 @@ func (o *pluginVerifyOptions) run(out io.Writer) error {
// Only support tarball verification
if fi.IsDir() {
return fmt.Errorf("directory verification not supported - only plugin tarballs can be verified")
return errors.New("directory verification not supported - only plugin tarballs can be verified")
}
// Verify it's a tarball
if !plugin.IsTarball(o.pluginPath) {
return fmt.Errorf("plugin file must be a gzipped tarball (.tar.gz or .tgz)")
return errors.New("plugin file must be a gzipped tarball (.tar.gz or .tgz)")
}
// Look for provenance file

@ -21,7 +21,7 @@ import (
"text/template"
)
func tpl(t string, vals map[string]interface{}, out io.Writer) error {
func tpl(t string, vals map[string]any, out io.Writer) error {
tt, err := template.New("_").Parse(t)
if err != nil {
return err

@ -342,7 +342,7 @@ func runPullTests(t *testing.T, tests []struct {
func buildOCIURL(registryURL, chartName, version, username, password string) string {
baseURL := fmt.Sprintf("oci://%s/u/ocitestuser/%s", registryURL, chartName)
if version != "" {
baseURL += fmt.Sprintf(" --version %s", version)
baseURL += " --version " + version
}
if username != "" && password != "" {
baseURL += fmt.Sprintf(" --username %s --password %s", username, password)
@ -416,23 +416,23 @@ func TestPullVersionCompletion(t *testing.T) {
tests := []cmdTestCase{{
name: "completion for pull version flag",
cmd: fmt.Sprintf("%s __complete pull testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete pull testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for pull version flag, no filter",
cmd: fmt.Sprintf("%s __complete pull testing/alpine --version 0.3", repoSetup),
cmd: repoSetup + " __complete pull testing/alpine --version 0.3",
golden: "output/version-comp.txt",
}, {
name: "completion for pull version flag too few args",
cmd: fmt.Sprintf("%s __complete pull --version ''", repoSetup),
cmd: repoSetup + " __complete pull --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for pull version flag too many args",
cmd: fmt.Sprintf("%s __complete pull testing/alpine badarg --version ''", repoSetup),
cmd: repoSetup + " __complete pull testing/alpine badarg --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for pull version flag invalid chart",
cmd: fmt.Sprintf("%s __complete pull invalid/invalid --version ''", repoSetup),
cmd: repoSetup + " __complete pull invalid/invalid --version ''",
golden: "output/version-invalid-comp.txt",
}}
runTestCmd(t, tests)

@ -196,15 +196,15 @@ func TestRepoRemoveCompletion(t *testing.T) {
// and that port changes each time we run the test.
tests := []cmdTestCase{{
name: "completion for repo remove",
cmd: fmt.Sprintf("%s __completeNoDesc repo remove ''", repoSetup),
cmd: repoSetup + " __completeNoDesc repo remove ''",
golden: "output/repo_list_comp.txt",
}, {
name: "completion for repo remove, no filter",
cmd: fmt.Sprintf("%s __completeNoDesc repo remove fo", repoSetup),
cmd: repoSetup + " __completeNoDesc repo remove fo",
golden: "output/repo_list_comp.txt",
}, {
name: "completion for repo remove repetition",
cmd: fmt.Sprintf("%s __completeNoDesc repo remove foo ''", repoSetup),
cmd: repoSetup + " __completeNoDesc repo remove foo ''",
golden: "output/repo_repeat_comp.txt",
}}
for _, test := range tests {

@ -17,6 +17,7 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"log/slog"
@ -136,7 +137,7 @@ func (h *hubSearchWriter) WriteTable(out io.Writer) error {
if len(h.elements) == 0 {
// Fail if no results found and --fail-on-no-result is enabled
if h.failOnNoResult {
return fmt.Errorf("no results found")
return errors.New("no results found")
}
_, err := out.Write([]byte("No results found\n"))
@ -175,7 +176,7 @@ func (h *hubSearchWriter) WriteYAML(out io.Writer) error {
func (h *hubSearchWriter) encodeByFormat(out io.Writer, format output.Format) error {
// Fail if no results found and --fail-on-no-result is enabled
if len(h.elements) == 0 && h.failOnNoResult {
return fmt.Errorf("no results found")
return errors.New("no results found")
}
// Initialize the array so no results returns an empty array instead of null

@ -216,7 +216,7 @@ func (r *repoSearchWriter) WriteTable(out io.Writer) error {
if len(r.results) == 0 {
// Fail if no results found and --fail-on-no-result is enabled
if r.failOnNoResult {
return fmt.Errorf("no results found")
return errors.New("no results found")
}
_, err := out.Write([]byte("No results found\n"))
@ -245,7 +245,7 @@ func (r *repoSearchWriter) WriteYAML(out io.Writer) error {
func (r *repoSearchWriter) encodeByFormat(out io.Writer, format output.Format) error {
// Fail if no results found and --fail-on-no-result is enabled
if len(r.results) == 0 && r.failOnNoResult {
return fmt.Errorf("no results found")
return errors.New("no results found")
}
// Initialize the array so no results returns an empty array instead of null
@ -307,7 +307,7 @@ func compListChartsOfRepo(repoName string, prefix string) []string {
// Provide dynamic auto-completion for commands that operate on charts (e.g., helm show)
// When true, the includeFiles argument indicates that completion should include local files (e.g., local charts)
func compListCharts(toComplete string, includeFiles bool) ([]string, cobra.ShellCompDirective) {
cobra.CompDebugln(fmt.Sprintf("compListCharts with toComplete %s", toComplete), settings.Debug)
cobra.CompDebugln("compListCharts with toComplete "+toComplete, settings.Debug)
noSpace := false
noFile := false
@ -323,7 +323,7 @@ func compListCharts(toComplete string, includeFiles bool) ([]string, cobra.Shell
if len(repoInfo) > 1 {
repoDesc = repoInfo[1]
}
repoWithSlash := fmt.Sprintf("%s/", repo)
repoWithSlash := repo + "/"
if strings.HasPrefix(toComplete, repoWithSlash) {
// Must complete with charts within the specified repo.
// Don't filter on toComplete to allow for shell fuzzy matching

@ -99,35 +99,35 @@ func TestShowVersionCompletion(t *testing.T) {
tests := []cmdTestCase{{
name: "completion for show version flag",
cmd: fmt.Sprintf("%s __complete show chart testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete show chart testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for show version flag, no filter",
cmd: fmt.Sprintf("%s __complete show chart testing/alpine --version 0.3", repoSetup),
cmd: repoSetup + " __complete show chart testing/alpine --version 0.3",
golden: "output/version-comp.txt",
}, {
name: "completion for show version flag too few args",
cmd: fmt.Sprintf("%s __complete show chart --version ''", repoSetup),
cmd: repoSetup + " __complete show chart --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for show version flag too many args",
cmd: fmt.Sprintf("%s __complete show chart testing/alpine badarg --version ''", repoSetup),
cmd: repoSetup + " __complete show chart testing/alpine badarg --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for show version flag invalid chart",
cmd: fmt.Sprintf("%s __complete show chart invalid/invalid --version ''", repoSetup),
cmd: repoSetup + " __complete show chart invalid/invalid --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for show version flag with all",
cmd: fmt.Sprintf("%s __complete show all testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete show all testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for show version flag with readme",
cmd: fmt.Sprintf("%s __complete show readme testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete show readme testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for show version flag with values",
cmd: fmt.Sprintf("%s __complete show values testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete show values testing/alpine --version ''",
golden: "output/version-comp.txt",
}}
runTestCmd(t, tests)

@ -197,9 +197,9 @@ func (s statusPrinter) WriteTable(out io.Writer) error {
}
_, _ = fmt.Fprintf(out, "TEST SUITE: %s\n%s\n%s\n%s\n",
h.Name,
fmt.Sprintf("Last Started: %s", h.LastRun.StartedAt.Format(time.ANSIC)),
fmt.Sprintf("Last Completed: %s", h.LastRun.CompletedAt.Format(time.ANSIC)),
fmt.Sprintf("Phase: %s", h.LastRun.Phase),
"Last Started: "+h.LastRun.StartedAt.Format(time.ANSIC),
"Last Completed: "+h.LastRun.CompletedAt.Format(time.ANSIC),
"Phase: "+h.LastRun.Phase,
)
}
}

@ -178,23 +178,23 @@ func TestTemplateVersionCompletion(t *testing.T) {
tests := []cmdTestCase{{
name: "completion for template version flag with release name",
cmd: fmt.Sprintf("%s __complete template releasename testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete template releasename testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for template version flag with generate-name",
cmd: fmt.Sprintf("%s __complete template --generate-name testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete template --generate-name testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for template version flag too few args",
cmd: fmt.Sprintf("%s __complete template testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete template testing/alpine --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for template version flag too many args",
cmd: fmt.Sprintf("%s __complete template releasename testing/alpine badarg --version ''", repoSetup),
cmd: repoSetup + " __complete template releasename testing/alpine badarg --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for template version flag invalid chart",
cmd: fmt.Sprintf("%s __complete template releasename invalid/invalid --version ''", repoSetup),
cmd: repoSetup + " __complete template releasename invalid/invalid --version ''",
golden: "output/version-invalid-comp.txt",
}}
runTestCmd(t, tests)

@ -149,7 +149,7 @@ func TestUpgradeCmd(t *testing.T) {
},
{
name: "upgrade a release with missing dependencies",
cmd: fmt.Sprintf("upgrade bonkers-bunny %s", missingDepsPath),
cmd: "upgrade bonkers-bunny " + missingDepsPath,
golden: "output/upgrade-with-missing-dependencies.txt",
wantError: true,
},
@ -161,7 +161,7 @@ func TestUpgradeCmd(t *testing.T) {
},
{
name: "upgrade a release with resolving missing dependencies",
cmd: fmt.Sprintf("upgrade --dependency-update funny-bunny %s", presentDepsPath),
cmd: "upgrade --dependency-update funny-bunny " + presentDepsPath,
golden: "output/upgrade-with-dependency-update.txt",
rels: []*release.Release{relMock("funny-bunny", 2, ch2)},
},
@ -443,23 +443,23 @@ func TestUpgradeVersionCompletion(t *testing.T) {
tests := []cmdTestCase{{
name: "completion for upgrade version flag",
cmd: fmt.Sprintf("%s __complete upgrade releasename testing/alpine --version ''", repoSetup),
cmd: repoSetup + " __complete upgrade releasename testing/alpine --version ''",
golden: "output/version-comp.txt",
}, {
name: "completion for upgrade version flag, no filter",
cmd: fmt.Sprintf("%s __complete upgrade releasename testing/alpine --version 0.3", repoSetup),
cmd: repoSetup + " __complete upgrade releasename testing/alpine --version 0.3",
golden: "output/version-comp.txt",
}, {
name: "completion for upgrade version flag too few args",
cmd: fmt.Sprintf("%s __complete upgrade releasename --version ''", repoSetup),
cmd: repoSetup + " __complete upgrade releasename --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for upgrade version flag too many args",
cmd: fmt.Sprintf("%s __complete upgrade releasename testing/alpine badarg --version ''", repoSetup),
cmd: repoSetup + " __complete upgrade releasename testing/alpine badarg --version ''",
golden: "output/version-invalid-comp.txt",
}, {
name: "completion for upgrade version flag invalid chart",
cmd: fmt.Sprintf("%s __complete upgrade releasename invalid/invalid --version ''", repoSetup),
cmd: repoSetup + " __complete upgrade releasename invalid/invalid --version ''",
golden: "output/version-invalid-comp.txt",
}}
runTestCmd(t, tests)
@ -636,7 +636,7 @@ func TestUpgradeInstallServerSideApply(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
store := storageFixture()
releaseName := fmt.Sprintf("ssa-test-%s", tt.expectedApplyMethod)
releaseName := "ssa-test-" + tt.expectedApplyMethod
cmd := fmt.Sprintf("upgrade %s --install %s '%s'", releaseName, tt.serverSideFlag, chartPath)
_, _, err := executeActionCommandC(store, cmd)

@ -129,8 +129,8 @@ func warnWrap(warn string) string {
// 'include' needs to be defined in the scope of a 'tpl' template as
// well as regular file-loaded templates.
func includeFun(t *template.Template, includedNames map[string]int) func(string, interface{}) (string, error) {
return func(name string, data interface{}) (string, error) {
func includeFun(t *template.Template, includedNames map[string]int) func(string, any) (string, error) {
return func(name string, data any) (string, error) {
var buf strings.Builder
if v, ok := includedNames[name]; ok {
if v > recursionMaxNums {
@ -150,8 +150,8 @@ func includeFun(t *template.Template, includedNames map[string]int) func(string,
// As does 'tpl', so that nested calls to 'tpl' see the templates
// defined by their enclosing contexts.
func tplFun(parent *template.Template, includedNames map[string]int, strict bool) func(string, interface{}) (string, error) {
return func(tpl string, vals interface{}) (string, error) {
func tplFun(parent *template.Template, includedNames map[string]int, strict bool) func(string, any) (string, error) {
return func(tpl string, vals any) (string, error) {
t, err := parent.Clone()
if err != nil {
return "", fmt.Errorf("cannot clone template: %w", err)
@ -204,7 +204,7 @@ func (e Engine) initFunMap(t *template.Template) {
funcMap["tpl"] = tplFun(t, includedNames, e.Strict)
// Add the `required` function here so we can use lintMode
funcMap["required"] = func(warn string, val interface{}) (interface{}, error) {
funcMap["required"] = func(warn string, val any) (any, error) {
if val == nil {
if e.LintMode {
// Don't fail on missing required values when linting
@ -319,7 +319,7 @@ func cleanupParseError(filename string, err error) error {
tokens := strings.Split(err.Error(), ": ")
if len(tokens) == 1 {
// This might happen if a non-templating error occurs
return fmt.Errorf("parse error in (%s): %s", filename, err)
return fmt.Errorf("parse error in (%s): %w", filename, err)
}
// The first token is "template"
// The second token is either "filename:lineno" or "filename:lineNo:columnNo"
@ -410,9 +410,7 @@ func parseTemplateSimpleErrorString(remainder string) (TraceableError, bool) {
// Executing form: "<templateName>: executing \"<funcName>\" at <<location>>: <errMsg>[ template:...]"
// Matches https://cs.opensource.google/go/go/+/refs/tags/go1.23.6:src/text/template/exec.go;l=141
func parseTemplateExecutingAtErrorType(remainder string) (TraceableError, bool) {
if idx := strings.Index(remainder, ": executing "); idx != -1 {
templateName := remainder[:idx]
after := remainder[idx+len(": executing "):]
if templateName, after, found := strings.Cut(remainder, ": executing "); found {
if len(after) == 0 || after[0] != '"' {
return TraceableError{}, false
}
@ -431,12 +429,10 @@ func parseTemplateExecutingAtErrorType(remainder string) (TraceableError, bool)
return TraceableError{}, false
}
afterAt := afterFunc[len(atPrefix):]
endLoc := strings.Index(afterAt, ">: ")
if endLoc == -1 {
locationName, errMsg, found := strings.Cut(afterAt, ">: ")
if !found {
return TraceableError{}, false
}
locationName := afterAt[:endLoc]
errMsg := afterAt[endLoc+len(">: "):]
// trim chained next error starting with space + "template:" if present
if cut := strings.Index(errMsg, " template:"); cut != -1 {
@ -466,7 +462,7 @@ func reformatExecErrorMsg(filename string, err error) error {
tokens := strings.SplitN(err.Error(), ": ", 3)
if len(tokens) != 3 {
// This might happen if a non-templating error occurs
return fmt.Errorf("execution error in (%s): %s", filename, err)
return fmt.Errorf("execution error in (%s): %w", filename, err)
}
// The first token is "template"
@ -535,9 +531,9 @@ func allTemplates(c ci.Charter, vals common.Values) map[string]renderable {
//
// As it recurses, it also sets the values to be appropriate for the template
// scope.
func recAllTpls(c ci.Charter, templates map[string]renderable, values common.Values) map[string]interface{} {
func recAllTpls(c ci.Charter, templates map[string]renderable, values common.Values) map[string]any {
vals := values.AsMap()
subCharts := make(map[string]interface{})
subCharts := make(map[string]any)
accessor, err := ci.NewAccessor(c)
if err != nil {
slog.Error("error accessing chart", "error", err)
@ -545,7 +541,7 @@ func recAllTpls(c ci.Charter, templates map[string]renderable, values common.Val
chartMetaData := accessor.MetadataAsMap()
chartMetaData["IsRoot"] = accessor.IsRoot()
next := map[string]interface{}{
next := map[string]any{
"Chart": chartMetaData,
"Files": newFiles(accessor.Files()),
"Release": vals["Release"],

@ -17,6 +17,7 @@ limitations under the License.
package engine
import (
"errors"
"fmt"
"path"
"strings"
@ -104,14 +105,14 @@ func TestRender(t *testing.T) {
{Name: "templates/test4", ModTime: modTime, Data: []byte("{{toJson .Values}}")},
{Name: "templates/test5", ModTime: modTime, Data: []byte("{{getHostByName \"helm.sh\"}}")},
},
Values: map[string]interface{}{"outer": "DEFAULT", "inner": "DEFAULT"},
Values: map[string]any{"outer": "DEFAULT", "inner": "DEFAULT"},
}
vals := map[string]interface{}{
"Values": map[string]interface{}{
vals := map[string]any{
"Values": map[string]any{
"outer": "spouter",
"inner": "inn",
"global": map[string]interface{}{
"global": map[string]any{
"callme": "Ishmael",
},
},
@ -226,11 +227,11 @@ func TestRenderWithDNS(t *testing.T) {
Templates: []*common.File{
{Name: "templates/test1", ModTime: time.Now(), Data: []byte("{{getHostByName \"helm.sh\"}}")},
},
Values: map[string]interface{}{},
Values: map[string]any{},
}
vals := map[string]interface{}{
"Values": map[string]interface{}{},
vals := map[string]any{
"Values": map[string]any{},
}
v, err := util.CoalesceValues(c, vals)
@ -277,15 +278,15 @@ var _ ClientProvider = &testClientProvider{}
// makeUnstructured is a convenience function for single-line creation of Unstructured objects.
func makeUnstructured(apiVersion, kind, name, namespace string) *unstructured.Unstructured {
ret := &unstructured.Unstructured{Object: map[string]interface{}{
ret := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": apiVersion,
"kind": kind,
"metadata": map[string]interface{}{
"metadata": map[string]any{
"name": name,
},
}}
if namespace != "" {
ret.Object["metadata"].(map[string]interface{})["namespace"] = namespace
ret.Object["metadata"].(map[string]any)["namespace"] = namespace
}
return ret
}
@ -356,7 +357,7 @@ func TestRenderWithClientProvider(t *testing.T) {
Name: "moby",
Version: "1.2.3",
},
Values: map[string]interface{}{},
Values: map[string]any{},
}
modTime := time.Now()
@ -368,8 +369,8 @@ func TestRenderWithClientProvider(t *testing.T) {
})
}
vals := map[string]interface{}{
"Values": map[string]interface{}{},
vals := map[string]any{
"Values": map[string]any{},
}
v, err := util.CoalesceValues(c, vals)
@ -401,11 +402,11 @@ func TestRenderWithClientProvider_error(t *testing.T) {
Templates: []*common.File{
{Name: "templates/error", ModTime: time.Now(), Data: []byte(`{{ lookup "v1" "Error" "" "" }}`)},
},
Values: map[string]interface{}{},
Values: map[string]any{},
}
vals := map[string]interface{}{
"Values": map[string]interface{}{},
vals := map[string]any{
"Values": map[string]any{},
}
v, err := util.CoalesceValues(c, vals)
@ -417,7 +418,7 @@ func TestRenderWithClientProvider_error(t *testing.T) {
t: t,
scheme: map[string]kindProps{
"v1/Error": {
shouldErr: fmt.Errorf("kaboom"),
shouldErr: errors.New("kaboom"),
},
},
}
@ -438,7 +439,7 @@ func TestParallelRenderInternals(t *testing.T) {
tpls := map[string]renderable{
"t": {
tpl: `{{.val}}`,
vals: map[string]interface{}{"val": tt},
vals: map[string]any{"val": tt},
},
}
out, err := e.render(tpls)
@ -455,7 +456,7 @@ func TestParallelRenderInternals(t *testing.T) {
}
func TestParseErrors(t *testing.T) {
vals := common.Values{"Values": map[string]interface{}{}}
vals := common.Values{"Values": map[string]any{}}
tplsUndefinedFunction := map[string]renderable{
"undefined_function": {tpl: `{{foo}}`, vals: vals},
@ -471,7 +472,7 @@ func TestParseErrors(t *testing.T) {
}
func TestExecErrors(t *testing.T) {
vals := common.Values{"Values": map[string]interface{}{}}
vals := common.Values{"Values": map[string]any{}}
cases := []struct {
name string
tpls map[string]renderable
@ -535,7 +536,7 @@ linebreak`,
}
func TestFailErrors(t *testing.T) {
vals := common.Values{"Values": map[string]interface{}{}}
vals := common.Values{"Values": map[string]any{}}
failtpl := `All your base are belong to us{{ fail "This is an error" }}`
tplsFailed := map[string]renderable{
@ -643,7 +644,7 @@ func TestRenderDependency(t *testing.T) {
},
})
out, err := Render(ch, map[string]interface{}{})
out, err := Render(ch, map[string]any{})
if err != nil {
t.Fatalf("failed to render chart: %s", err)
}
@ -675,7 +676,7 @@ func TestRenderNestedValues(t *testing.T) {
{Name: deepestpath, ModTime: modTime, Data: []byte(`And this same {{.Values.what}} that smiles {{.Values.global.when}}`)},
{Name: checkrelease, ModTime: modTime, Data: []byte(`Tomorrow will be {{default "happy" .Release.Name }}`)},
},
Values: map[string]interface{}{"what": "milkshake", "where": "here"},
Values: map[string]any{"what": "milkshake", "where": "here"},
}
inner := &chart.Chart{
@ -683,7 +684,7 @@ func TestRenderNestedValues(t *testing.T) {
Templates: []*common.File{
{Name: innerpath, ModTime: modTime, Data: []byte(`Old {{.Values.who}} is still a-flyin'`)},
},
Values: map[string]interface{}{"who": "Robert", "what": "glasses"},
Values: map[string]any{"who": "Robert", "what": "glasses"},
}
inner.AddDependency(deepest)
@ -693,10 +694,10 @@ func TestRenderNestedValues(t *testing.T) {
{Name: outerpath, ModTime: modTime, Data: []byte(`Gather ye {{.Values.what}} while ye may`)},
{Name: subchartspath, ModTime: modTime, Data: []byte(`The glorious Lamp of {{.Subcharts.herrick.Subcharts.deepest.Values.where}}, the {{.Subcharts.herrick.Values.what}}`)},
},
Values: map[string]interface{}{
Values: map[string]any{
"what": "stinkweed",
"who": "me",
"herrick": map[string]interface{}{
"herrick": map[string]any{
"who": "time",
"what": "Sun",
},
@ -704,15 +705,15 @@ func TestRenderNestedValues(t *testing.T) {
}
outer.AddDependency(inner)
injValues := map[string]interface{}{
injValues := map[string]any{
"what": "rosebuds",
"herrick": map[string]interface{}{
"deepest": map[string]interface{}{
"herrick": map[string]any{
"deepest": map[string]any{
"what": "flower",
"where": "Heaven",
},
},
"global": map[string]interface{}{
"global": map[string]any{
"when": "to-day",
},
}
@ -1059,9 +1060,11 @@ func TestRenderRecursionLimit(t *testing.T) {
}
var expect string
var expectSb1062 strings.Builder
for range times {
expect += phrase + "\n"
expectSb1062.WriteString(phrase + "\n")
}
expect += expectSb1062.String()
if got := out["overlook/templates/quote"]; got != expect {
t.Errorf("Expected %q, got %q (%v)", expect, got, out)
}
@ -1349,7 +1352,7 @@ NestedHelperFunctions/charts/common/templates/_helpers_2.tpl:1:49
v := common.Values{}
val, _ := util.CoalesceValues(c, v)
vals := map[string]interface{}{
vals := map[string]any{
"Values": val.AsMap(),
}
_, err := Render(c, vals)
@ -1383,7 +1386,7 @@ template: no template "nested_helper.name" associated with template "gotpl"`
v := common.Values{}
val, _ := util.CoalesceValues(c, v)
vals := map[string]interface{}{
vals := map[string]any{
"Values": val.AsMap(),
}
_, err := Render(c, vals)

@ -64,13 +64,13 @@ func funcMap() template.FuncMap {
// This is a placeholder for the "include" function, which is
// late-bound to a template. By declaring it here, we preserve the
// integrity of the linter.
"include": func(string, interface{}) string { return "not implemented" },
"tpl": func(string, interface{}) interface{} { return "not implemented" },
"required": func(string, interface{}) (interface{}, error) { return "not implemented", nil },
"include": func(string, any) string { return "not implemented" },
"tpl": func(string, any) any { return "not implemented" },
"required": func(string, any) (any, error) { return "not implemented", nil },
// Provide a placeholder for the "lookup" function, which requires a kubernetes
// connection.
"lookup": func(string, string, string, string) (map[string]interface{}, error) {
return map[string]interface{}{}, nil
"lookup": func(string, string, string, string) (map[string]any, error) {
return map[string]any{}, nil
},
}
@ -83,7 +83,7 @@ func funcMap() template.FuncMap {
// always return a string, even on marshal error (empty string).
//
// This is designed to be called from a template.
func toYAML(v interface{}) string {
func toYAML(v any) string {
data, err := yaml.Marshal(v)
if err != nil {
// Swallow errors inside of a template.
@ -97,7 +97,7 @@ func toYAML(v interface{}) string {
//
// This is designed to be called from a template when need to ensure that the
// output YAML is valid.
func mustToYAML(v interface{}) string {
func mustToYAML(v any) string {
data, err := yaml.Marshal(v)
if err != nil {
panic(err)
@ -105,7 +105,7 @@ func mustToYAML(v interface{}) string {
return strings.TrimSuffix(string(data), "\n")
}
func toYAMLPretty(v interface{}) string {
func toYAMLPretty(v any) string {
var data bytes.Buffer
encoder := goYaml.NewEncoder(&data)
encoder.SetIndent(2)
@ -124,8 +124,8 @@ func toYAMLPretty(v interface{}) string {
// YAML documents. Additionally, because its intended use is within templates
// it tolerates errors. It will insert the returned error message string into
// m["Error"] in the returned map.
func fromYAML(str string) map[string]interface{} {
m := map[string]interface{}{}
func fromYAML(str string) map[string]any {
m := map[string]any{}
if err := yaml.Unmarshal([]byte(str), &m); err != nil {
m["Error"] = err.Error()
@ -139,11 +139,11 @@ func fromYAML(str string) map[string]interface{} {
// YAML documents. Additionally, because its intended use is within templates
// it tolerates errors. It will insert the returned error message string as
// the first and only item in the returned array.
func fromYAMLArray(str string) []interface{} {
a := []interface{}{}
func fromYAMLArray(str string) []any {
a := []any{}
if err := yaml.Unmarshal([]byte(str), &a); err != nil {
a = []interface{}{err.Error()}
a = []any{err.Error()}
}
return a
}
@ -152,7 +152,7 @@ func fromYAMLArray(str string) []interface{} {
// always return a string, even on marshal error (empty string).
//
// This is designed to be called from a template.
func toTOML(v interface{}) string {
func toTOML(v any) string {
b := bytes.NewBuffer(nil)
e := toml.NewEncoder(b)
err := e.Encode(v)
@ -168,8 +168,8 @@ func toTOML(v interface{}) string {
// TOML documents. Additionally, because its intended use is within templates
// it tolerates errors. It will insert the returned error message string into
// m["Error"] in the returned map.
func fromTOML(str string) map[string]interface{} {
m := make(map[string]interface{})
func fromTOML(str string) map[string]any {
m := make(map[string]any)
if err := toml.Unmarshal([]byte(str), &m); err != nil {
m["Error"] = err.Error()
@ -181,7 +181,7 @@ func fromTOML(str string) map[string]interface{} {
// always return a string, even on marshal error (empty string).
//
// This is designed to be called from a template.
func toJSON(v interface{}) string {
func toJSON(v any) string {
data, err := json.Marshal(v)
if err != nil {
// Swallow errors inside of a template.
@ -195,7 +195,7 @@ func toJSON(v interface{}) string {
//
// This is designed to be called from a template when need to ensure that the
// output JSON is valid.
func mustToJSON(v interface{}) string {
func mustToJSON(v any) string {
data, err := json.Marshal(v)
if err != nil {
panic(err)
@ -209,8 +209,8 @@ func mustToJSON(v interface{}) string {
// JSON documents. Additionally, because its intended use is within templates
// it tolerates errors. It will insert the returned error message string into
// m["Error"] in the returned map.
func fromJSON(str string) map[string]interface{} {
m := make(map[string]interface{})
func fromJSON(str string) map[string]any {
m := make(map[string]any)
if err := json.Unmarshal([]byte(str), &m); err != nil {
m["Error"] = err.Error()
@ -224,11 +224,11 @@ func fromJSON(str string) map[string]interface{} {
// JSON documents. Additionally, because its intended use is within templates
// it tolerates errors. It will insert the returned error message string as
// the first and only item in the returned array.
func fromJSONArray(str string) []interface{} {
a := []interface{}{}
func fromJSONArray(str string) []any {
a := []any{}
if err := json.Unmarshal([]byte(str), &a); err != nil {
a = []interface{}{err.Error()}
a = []any{err.Error()}
}
return a
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save