diff --git a/cmd/helm/get_all.go b/cmd/helm/get_all.go index 2dbef97cf..0d773638e 100644 --- a/cmd/helm/get_all.go +++ b/cmd/helm/get_all.go @@ -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) diff --git a/cmd/helm/get_values.go b/cmd/helm/get_values.go index 6124e1b33..fa537393a 100644 --- a/cmd/helm/get_values.go +++ b/cmd/helm/get_values.go @@ -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 } diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index 553da5098..b27e9496b 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -43,14 +43,14 @@ func init() { log.SetFlags(log.Lshortfile) } -func debug(format string, v ...interface{}) { +func debug(format string, v ...any) { if settings.Debug { format = fmt.Sprintf("[debug] %s\n", format) log.Output(2, fmt.Sprintf(format, v...)) } } -func warning(format string, v ...interface{}) { +func warning(format string, v ...any) { format = fmt.Sprintf("WARNING: %s\n", format) fmt.Fprintf(os.Stderr, format, v...) } diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go index b20b1a24d..4816da6bf 100644 --- a/cmd/helm/helm_test.go +++ b/cmd/helm/helm_test.go @@ -94,7 +94,7 @@ func executeActionCommandStdinC(store *storage.Storage, in *os.File, cmd string) Releases: store, KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard}, Capabilities: chartutil.DefaultCapabilities, - Log: func(format string, v ...interface{}) {}, + Log: func(format string, v ...any) {}, } root, err := newRootCmd(actionConfig, buf, args) diff --git a/cmd/helm/printer.go b/cmd/helm/printer.go index 7cf7bf994..0c2c34292 100644 --- a/cmd/helm/printer.go +++ b/cmd/helm/printer.go @@ -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 diff --git a/internal/monocular/client.go b/internal/monocular/client.go index 88a2564b9..f02e0dd1e 100644 --- a/internal/monocular/client.go +++ b/internal/monocular/client.go @@ -31,7 +31,7 @@ type Client struct { BaseURL string // The internal logger to use - Log func(string, ...interface{}) + Log func(string, ...any) } // New creates a new client @@ -48,7 +48,7 @@ func New(u string) (*Client, error) { }, nil } -var nopLogger = func(_ string, _ ...interface{}) {} +var nopLogger = func(_ string, _ ...any) {} // Validate if the base URL for monocular is valid. func validate(u string) error { diff --git a/internal/test/test.go b/internal/test/test.go index e6821282c..acb6a9b22 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -30,8 +30,8 @@ var updateGolden = flag.Bool("update", false, "update golden files") // TestingT describes a testing object compatible with the critical functions from the testing.T type type TestingT interface { - Fatal(...interface{}) - Fatalf(string, ...interface{}) + Fatal(...any) + Fatalf(string, ...any) HelperT } diff --git a/pkg/action/action.go b/pkg/action/action.go index 016aec3f6..920fda3ac 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -94,7 +94,7 @@ type Configuration struct { // Capabilities describes the capabilities of the Kubernetes cluster. Capabilities *chartutil.Capabilities - Log func(string, ...interface{}) + Log func(string, ...any) } // renderResources renders the templates in a chart @@ -238,7 +238,7 @@ type RESTClientGetter interface { } // DebugLog sets the logger that writes debug strings -type DebugLog func(format string, v ...interface{}) +type DebugLog func(format string, v ...any) // capabilities builds a Capabilities from discovery information. func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) { @@ -327,7 +327,7 @@ func GetVersionSet(client discovery.ServerResourcesInterface) (chartutil.Version return chartutil.DefaultVersionSet, nil } - versionMap := make(map[string]interface{}) + versionMap := make(map[string]any) versions := []string{} // Extract the groups diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index c4ef6c056..8b6db04cf 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -47,7 +47,7 @@ func actionConfigFixture(t *testing.T) *Configuration { KubeClient: &kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: io.Discard}}, Capabilities: chartutil.DefaultCapabilities, RegistryClient: registryClient, - Log: func(format string, v ...interface{}) { + Log: func(format string, v ...any) { t.Helper() if *verbose { t.Logf(format, v...) @@ -139,12 +139,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", }, }, @@ -155,7 +155,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 } @@ -240,7 +240,7 @@ func namedReleaseStub(name string, status release.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{ { diff --git a/pkg/action/get_values.go b/pkg/action/get_values.go index 9c32db213..6e5c09fca 100644 --- a/pkg/action/get_values.go +++ b/pkg/action/get_values.go @@ -38,7 +38,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 } diff --git a/pkg/action/install.go b/pkg/action/install.go index d5c34cef7..6a5cd70b2 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -205,13 +205,13 @@ func (i *Install) installCRDs(crds []chart.CRD) error { // // If DryRun is set to true, this will prepare the release, but not install it -func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) { +func (i *Install) Run(chrt *chart.Chart, vals map[string]any) (*release.Release, error) { ctx := context.Background() return i.RunWithContext(ctx, chrt, vals) } // Run executes the installation with Context -func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) { +func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals map[string]any) (*release.Release, error) { // Check reachability of cluster unless in client-only mode (e.g. `helm template` without `--validate`) if !i.ClientOnly { if err := i.cfg.KubeClient.IsReachable(); err != nil { @@ -513,7 +513,7 @@ func (i *Install) availableName() error { } // createRelease creates a new release object -func (i *Install) createRelease(chrt *chart.Chart, rawVals map[string]interface{}) *release.Release { +func (i *Install) createRelease(chrt *chart.Chart, rawVals map[string]any) *release.Release { ts := i.cfg.Now() return &release.Release{ Name: i.ReleaseName, diff --git a/pkg/action/install_test.go b/pkg/action/install_test.go index dd0cdb54d..f9d6d20eb 100644 --- a/pkg/action/install_test.go +++ b/pkg/action/install_test.go @@ -59,7 +59,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(context.Background()) res, err := instAction.RunWithContext(ctx, buildChart(), vals) if err != nil { @@ -93,13 +93,13 @@ func TestInstallRelease(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", }, } @@ -138,7 +138,7 @@ func TestInstallReleaseClientOnly(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") @@ -150,7 +150,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{} res, err := instAction.Run(buildChart(withNotes("note here")), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -177,7 +177,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{} res, err := instAction.Run(buildChart(withNotes("got-{{.Release.Name}}")), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -196,7 +196,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{} res, err := instAction.Run(buildChart(withNotes("parent"), withDependency(withNotes("child"))), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -215,7 +215,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{} res, err := instAction.Run(buildChart(withNotes("parent"), withDependency(withNotes("child"))), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -235,7 +235,7 @@ func TestInstallRelease_DryRun(t *testing.T) { is := assert.New(t) instAction := installAction(t) instAction.DryRun = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(withSampleTemplates()), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -259,7 +259,7 @@ func TestInstallRelease_DryRun_Lookup(t *testing.T) { is := assert.New(t) instAction := installAction(t) instAction.DryRun = true - vals := map[string]interface{}{} + vals := map[string]any{} mockChart := buildChart(withSampleTemplates()) mockChart.Templates = append(mockChart.Templates, &chart.File{ @@ -279,7 +279,7 @@ func TestInstallReleaseIncorrectTemplate_DryRun(t *testing.T) { is := assert.New(t) instAction := installAction(t) instAction.DryRun = true - vals := map[string]interface{}{} + vals := map[string]any{} _, err := instAction.Run(buildChart(withSampleIncludingIncorrectTemplates()), vals) expectedErr := "\"hello/templates/incorrect\" at <.Values.bad.doh>: nil pointer evaluating interface {}.doh" if err == nil { @@ -297,7 +297,7 @@ func TestInstallRelease_NoHooks(t *testing.T) { instAction.ReleaseName = "no-hooks" instAction.cfg.Releases.Create(releaseStub()) - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) if err != nil { t.Fatalf("Failed install: %s", err) @@ -314,7 +314,7 @@ func TestInstallRelease_FailedHooks(t *testing.T) { failer.WatchUntilReadyError = fmt.Errorf("Failed watch") instAction.cfg.KubeClient = failer - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) is.Error(err) is.Contains(res.Info.Description, "failed post-install") @@ -331,7 +331,7 @@ func TestInstallRelease_ReplaceRelease(t *testing.T) { instAction.cfg.Releases.Create(rel) instAction.ReleaseName = rel.Name - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) is.NoError(err) @@ -347,13 +347,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") @@ -367,7 +367,7 @@ func TestInstallRelease_Wait(t *testing.T) { failer.WaitError = fmt.Errorf("I timed out") instAction.cfg.KubeClient = failer instAction.Wait = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) is.Error(err) @@ -382,7 +382,7 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) { failer.WaitDuration = 10 * time.Second instAction.cfg.KubeClient = failer instAction.Wait = true - vals := map[string]interface{}{} + vals := map[string]any{} ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -402,7 +402,7 @@ func TestInstallRelease_WaitForJobs(t *testing.T) { instAction.cfg.KubeClient = failer instAction.Wait = true instAction.WaitForJobs = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) is.Error(err) @@ -420,7 +420,7 @@ func TestInstallRelease_Atomic(t *testing.T) { failer.WaitError = fmt.Errorf("I timed out") instAction.cfg.KubeClient = failer instAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := instAction.Run(buildChart(), vals) is.Error(err) @@ -441,7 +441,7 @@ func TestInstallRelease_Atomic(t *testing.T) { failer.DeleteError = fmt.Errorf("uninstall fail") instAction.cfg.KubeClient = failer instAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} _, err := instAction.Run(buildChart(), vals) is.Error(err) @@ -459,7 +459,7 @@ func TestInstallRelease_Atomic_Interrupted(t *testing.T) { failer.WaitDuration = 10 * time.Second instAction.cfg.KubeClient = failer instAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -549,7 +549,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() @@ -581,7 +581,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() diff --git a/pkg/action/lint.go b/pkg/action/lint.go index adb8ebcab..9c926fa1f 100644 --- a/pkg/action/lint.go +++ b/pkg/action/lint.go @@ -51,7 +51,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 @@ -85,7 +85,7 @@ func HasWarningsOrErrors(result *LintResult) bool { return false } -func lintChart(path string, vals map[string]interface{}, namespace string, strict bool) (support.Linter, error) { +func lintChart(path string, vals map[string]any, namespace string, strict bool) (support.Linter, error) { var chartPath string linter := support.Linter{} diff --git a/pkg/action/lint_test.go b/pkg/action/lint_test.go index 1828461f3..22f24bb78 100644 --- a/pkg/action/lint_test.go +++ b/pkg/action/lint_test.go @@ -21,7 +21,7 @@ import ( ) var ( - values = make(map[string]interface{}) + values = make(map[string]any) namespace = "testNamespace" strict = false chart1MultipleChartLint = "testdata/charts/multiplecharts-lint-chart-1" @@ -78,7 +78,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, strict) + _, err := lintChart(tt.chartPath, map[string]any{}, namespace, strict) switch { case err != nil && !tt.err: t.Errorf("%s", err) diff --git a/pkg/action/package.go b/pkg/action/package.go index 698169032..2ba9eb064 100644 --- a/pkg/action/package.go +++ b/pkg/action/package.go @@ -54,7 +54,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, vals map[string]interface{}) (string, error) { +func (p *Package) Run(path string, vals map[string]any) (string, error) { ch, err := loader.LoadDir(path) if err != nil { return "", err diff --git a/pkg/action/show_test.go b/pkg/action/show_test.go index 8b617ea85..a9ee4b339 100644 --- a/pkg/action/show_test.go +++ b/pkg/action/show_test.go @@ -36,7 +36,7 @@ func TestShow(t *testing.T) { Raw: []*chart.File{ {Name: "values.yaml", Data: []byte("VALUES\n")}, }, - Values: map[string]interface{}{}, + Values: map[string]any{}, } output, err := client.Run("") diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 829be51df..6ccaf2451 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -129,13 +129,13 @@ func (u *Upgrade) SetRegistryClient(client *registry.Client) { } // Run executes the upgrade on the given release. -func (u *Upgrade) Run(name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, error) { +func (u *Upgrade) Run(name string, chart *chart.Chart, vals map[string]any) (*release.Release, error) { ctx := context.Background() return u.RunWithContext(ctx, name, chart, vals) } // RunWithContext executes the upgrade on the given release with context. -func (u *Upgrade) RunWithContext(ctx context.Context, name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, error) { +func (u *Upgrade) RunWithContext(ctx context.Context, name string, chart *chart.Chart, vals map[string]any) (*release.Release, error) { if err := u.cfg.KubeClient.IsReachable(); err != nil { return nil, err } @@ -172,7 +172,7 @@ func (u *Upgrade) RunWithContext(ctx context.Context, name string, chart *chart. } // prepareUpgrade builds an upgraded release for an upgrade operation. -func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, *release.Release, error) { +func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[string]any) (*release.Release, *release.Release, error) { if chart == nil { return nil, nil, errMissingChart } @@ -333,7 +333,7 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR } rChan := make(chan resultMessage) ctxChan := make(chan resultMessage) - doneChan := make(chan interface{}) + doneChan := make(chan any) defer close(doneChan) go u.releasingUpgrade(rChan, upgradedRelease, current, target, originalRelease) go u.handleContext(ctx, doneChan, ctxChan, upgradedRelease) @@ -358,7 +358,7 @@ func (u *Upgrade) reportToPerformUpgrade(c chan<- resultMessage, rel *release.Re } // Setup listener for SIGINT and SIGTERM -func (u *Upgrade) handleContext(ctx context.Context, done chan interface{}, c chan<- resultMessage, upgradedRelease *release.Release) { +func (u *Upgrade) handleContext(ctx context.Context, done chan any, c chan<- resultMessage, upgradedRelease *release.Release) { select { case <-ctx.Done(): err := ctx.Err() @@ -504,7 +504,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e // // This is skipped if the u.ResetValues flag is set, in which case the // request values are not altered. -func (u *Upgrade) reuseValues(chart *chart.Chart, current *release.Release, newVals map[string]interface{}) (map[string]interface{}, error) { +func (u *Upgrade) reuseValues(chart *chart.Chart, current *release.Release, newVals map[string]any) (map[string]any, error) { if u.ResetValues { // If ResetValues is set, we completely ignore current.Config. u.cfg.Log("resetting values to the chart's original version") diff --git a/pkg/action/upgrade_test.go b/pkg/action/upgrade_test.go index 62922b373..c16d1df1e 100644 --- a/pkg/action/upgrade_test.go +++ b/pkg/action/upgrade_test.go @@ -51,7 +51,7 @@ func TestUpgradeRelease_Success(t *testing.T) { req.NoError(upAction.cfg.Releases.Create(rel)) upAction.Wait = true - vals := map[string]interface{}{} + vals := map[string]any{} ctx, done := context.WithCancel(context.Background()) res, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals) @@ -81,7 +81,7 @@ func TestUpgradeRelease_Wait(t *testing.T) { failer.WaitError = fmt.Errorf("I timed out") upAction.cfg.KubeClient = failer upAction.Wait = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := upAction.Run(rel.Name, buildChart(), vals) req.Error(err) @@ -104,7 +104,7 @@ func TestUpgradeRelease_WaitForJobs(t *testing.T) { upAction.cfg.KubeClient = failer upAction.Wait = true upAction.WaitForJobs = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := upAction.Run(rel.Name, buildChart(), vals) req.Error(err) @@ -128,7 +128,7 @@ func TestUpgradeRelease_CleanupOnFail(t *testing.T) { upAction.cfg.KubeClient = failer upAction.Wait = true upAction.CleanupOnFail = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := upAction.Run(rel.Name, buildChart(), vals) req.Error(err) @@ -154,7 +154,7 @@ func TestUpgradeRelease_Atomic(t *testing.T) { failer.WatchUntilReadyError = fmt.Errorf("arming key removed") upAction.cfg.KubeClient = failer upAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} res, err := upAction.Run(rel.Name, buildChart(), vals) req.Error(err) @@ -179,7 +179,7 @@ func TestUpgradeRelease_Atomic(t *testing.T) { failer.UpdateError = fmt.Errorf("update fail") upAction.cfg.KubeClient = failer upAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} _, err := upAction.Run(rel.Name, buildChart(), vals) req.Error(err) @@ -194,17 +194,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", @@ -238,8 +238,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, }, } @@ -255,8 +255,8 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) { withMetadataDependency(dependency), ) now := helmtime.Now() - existingValues := map[string]interface{}{ - "subchart": map[string]interface{}{ + existingValues := map[string]any{ + "subchart": map[string]any{ "enabled": false, }, } @@ -283,7 +283,7 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) { withMetadataDependency(dependency), ) // reusing values and upgrading - res, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]interface{}{}) + res, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]any{}) is.NoError(err) // Now get the upgraded release @@ -297,8 +297,8 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) { is.Equal(release.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, }, } @@ -320,7 +320,7 @@ func TestUpgradeRelease_Pending(t *testing.T) { rel2.Version = 2 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) @@ -341,7 +341,7 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) { failer.WaitDuration = 10 * time.Second upAction.cfg.KubeClient = failer upAction.Wait = true - vals := map[string]interface{}{} + vals := map[string]any{} ctx := context.Background() ctx, cancel := context.WithCancel(ctx) @@ -370,7 +370,7 @@ func TestUpgradeRelease_Interrupted_Atomic(t *testing.T) { failer.WaitDuration = 5 * time.Second upAction.cfg.KubeClient = failer upAction.Atomic = true - vals := map[string]interface{}{} + vals := map[string]any{} ctx := context.Background() ctx, cancel := context.WithCancel(ctx) diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go index a3bed63a3..7deb8986e 100644 --- a/pkg/chart/chart.go +++ b/pkg/chart/chart.go @@ -45,7 +45,7 @@ type Chart struct { // Templates for this chart. Templates []*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"` // Files are miscellaneous files in a chart archive, diff --git a/pkg/chart/dependency.go b/pkg/chart/dependency.go index 4ef5eeb32..cb3363f0f 100644 --- a/pkg/chart/dependency.go +++ b/pkg/chart/dependency.go @@ -44,7 +44,7 @@ type Dependency struct { Enabled bool `json:"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"` + ImportValues []any `json:"import-values,omitempty"` // Alias usable alias to be used for the chart Alias string `json:"alias,omitempty"` } diff --git a/pkg/chart/errors.go b/pkg/chart/errors.go index 2fad5f370..056529efa 100644 --- a/pkg/chart/errors.go +++ b/pkg/chart/errors.go @@ -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...)) } diff --git a/pkg/chart/loader/load.go b/pkg/chart/loader/load.go index 7cc8878a8..e01a9c041 100644 --- a/pkg/chart/loader/load.go +++ b/pkg/chart/loader/load.go @@ -103,7 +103,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { return c, errors.Wrap(err, "cannot load Chart.lock") } case f.Name == "values.yaml": - c.Values = make(map[string]interface{}) + c.Values = make(map[string]any) if err := yaml.Unmarshal(f.Data, &c.Values); err != nil { return c, errors.Wrap(err, "cannot load values.yaml") } diff --git a/pkg/chartutil/coalesce.go b/pkg/chartutil/coalesce.go index 68bc9aa6f..027ff221f 100644 --- a/pkg/chartutil/coalesce.go +++ b/pkg/chartutil/coalesce.go @@ -42,41 +42,41 @@ func concatPrefix(a, b string) string { // - Scalar values and arrays are replaced, maps are merged // - A chart has access to all of the variables for it, as well as all of // the values destined for its dependencies. -func CoalesceValues(chrt *chart.Chart, vals map[string]interface{}) (Values, error) { +func CoalesceValues(chrt *chart.Chart, vals map[string]any) (Values, error) { v, err := copystructure.Copy(vals) if err != nil { return vals, err } - valsCopy := v.(map[string]interface{}) + valsCopy := v.(map[string]any) // if we have an empty map, make sure it is initialized if valsCopy == nil { - valsCopy = make(map[string]interface{}) + valsCopy = make(map[string]any) } return coalesce(log.Printf, chrt, valsCopy, "") } -type printFn func(format string, v ...interface{}) +type printFn func(format string, v ...any) // coalesce coalesces the dest values and the chart values, giving priority to the dest values. // // This is a helper function for CoalesceValues. -func coalesce(printf printFn, ch *chart.Chart, dest map[string]interface{}, prefix string) (map[string]interface{}, error) { +func coalesce(printf printFn, ch *chart.Chart, dest map[string]any, prefix string) (map[string]any, error) { coalesceValues(printf, ch, dest, prefix) return coalesceDeps(printf, ch, dest, prefix) } // coalesceDeps coalesces the dependencies of the given chart. -func coalesceDeps(printf printFn, chrt *chart.Chart, dest map[string]interface{}, prefix string) (map[string]interface{}, error) { +func coalesceDeps(printf printFn, chrt *chart.Chart, dest map[string]any, prefix string) (map[string]any, error) { for _, subchart := range chrt.Dependencies() { if c, ok := dest[subchart.Name()]; !ok { // If dest doesn't already have the key, create it. - dest[subchart.Name()] = make(map[string]interface{}) + dest[subchart.Name()] = make(map[string]any) } else if !istable(c) { return dest, errors.Errorf("type mismatch on %s: %t", subchart.Name(), c) } if dv, ok := dest[subchart.Name()]; ok { - dvmap := dv.(map[string]interface{}) + dvmap := dv.(map[string]any) subPrefix := concatPrefix(prefix, chrt.Metadata.Name) // Get globals out of dest and merge them into dvmap. @@ -96,19 +96,19 @@ func coalesceDeps(printf printFn, chrt *chart.Chart, dest map[string]interface{} // coalesceGlobals copies the globals out of src and merges them into dest. // // For convenience, returns dest. -func coalesceGlobals(printf printFn, dest, src map[string]interface{}, prefix string) { - var dg, sg map[string]interface{} +func coalesceGlobals(printf printFn, dest, src map[string]any, prefix string) { + var dg, sg map[string]any if destglob, ok := dest[GlobalKey]; !ok { - dg = make(map[string]interface{}) - } else if dg, ok = destglob.(map[string]interface{}); !ok { + dg = make(map[string]any) + } else if dg, ok = destglob.(map[string]any); !ok { printf("warning: skipping globals because destination %s is not a table.", GlobalKey) return } if srcglob, ok := src[GlobalKey]; !ok { - sg = make(map[string]interface{}) - } else if sg, ok = srcglob.(map[string]interface{}); !ok { + sg = make(map[string]any) + } else if sg, ok = srcglob.(map[string]any); !ok { printf("warning: skipping globals because source %s is not a table.", GlobalKey) return } @@ -119,12 +119,12 @@ func coalesceGlobals(printf printFn, dest, src map[string]interface{}, prefix st // tables in globals. for key, val := range sg { if istable(val) { - vv := copyMap(val.(map[string]interface{})) + vv := copyMap(val.(map[string]any)) if destv, ok := dg[key]; !ok { // Here there is no merge. We're just adding. dg[key] = vv } else { - if destvmap, ok := destv.(map[string]interface{}); !ok { + if destvmap, ok := destv.(map[string]any); !ok { printf("Conflict: cannot merge map onto non-map for %q. Skipping.", key) } else { // Basically, we reverse order of coalesce here to merge @@ -145,8 +145,8 @@ func coalesceGlobals(printf printFn, dest, src map[string]interface{}, prefix st dest[GlobalKey] = dg } -func copyMap(src map[string]interface{}) map[string]interface{} { - m := make(map[string]interface{}, len(src)) +func copyMap(src map[string]any) map[string]any { + m := make(map[string]any, len(src)) for k, v := range src { m[k] = v } @@ -156,7 +156,7 @@ func copyMap(src map[string]interface{}) map[string]interface{} { // coalesceValues builds up a values map for a particular chart. // // Values in v will override the values in the chart. -func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, prefix string) { +func coalesceValues(printf printFn, c *chart.Chart, v map[string]any, prefix string) { subPrefix := concatPrefix(prefix, c.Metadata.Name) for key, val := range c.Values { if value, ok := v[key]; ok { @@ -165,9 +165,9 @@ func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, pr // This allows Helm's various sources of values (value files or --set) to // remove incompatible keys from any previous chart, file, or set values. delete(v, key) - } else if dest, ok := value.(map[string]interface{}); ok { + } else if dest, ok := value.(map[string]any); ok { // if v[key] is a table, merge nv's val table into v[key]. - src, ok := val.(map[string]interface{}) + src, ok := val.(map[string]any) if !ok { // If the original value is nil, there is nothing to coalesce, so we don't print // the warning @@ -190,14 +190,14 @@ func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, pr // CoalesceTables merges a source map into a destination map. // // dest is considered authoritative. -func CoalesceTables(dst, src map[string]interface{}) map[string]interface{} { +func CoalesceTables(dst, src map[string]any) map[string]any { return coalesceTablesFullKey(log.Printf, dst, src, "") } // coalesceTablesFullKey merges a source map into a destination map. // // dest is considered authoritative. -func coalesceTablesFullKey(printf printFn, dst, src map[string]interface{}, prefix string) map[string]interface{} { +func coalesceTablesFullKey(printf printFn, dst, src map[string]any, prefix string) map[string]any { // When --reuse-values is set but there are no modifications yet, return new values if src == nil { return dst @@ -215,7 +215,7 @@ func coalesceTablesFullKey(printf printFn, dst, src map[string]interface{}, pref dst[key] = val } else if istable(val) { if istable(dv) { - coalesceTablesFullKey(printf, dv.(map[string]interface{}), val.(map[string]interface{}), fullkey) + coalesceTablesFullKey(printf, dv.(map[string]any), val.(map[string]any), fullkey) } else { printf("warning: cannot overwrite table with non table for %s (%v)", fullkey, val) } diff --git a/pkg/chartutil/coalesce_test.go b/pkg/chartutil/coalesce_test.go index 3fe93f5ff..75921e6ca 100644 --- a/pkg/chartutil/coalesce_test.go +++ b/pkg/chartutil/coalesce_test.go @@ -68,52 +68,52 @@ func TestCoalesceValues(t *testing.T) { c := withDeps(&chart.Chart{ Metadata: &chart.Metadata{Name: "moby"}, - Values: map[string]interface{}{ + Values: map[string]any{ "back": "exists", "bottom": "exists", "front": "exists", "left": "exists", "name": "moby", - "nested": map[string]interface{}{"boat": true}, + "nested": map[string]any{"boat": true}, "override": "bad", "right": "exists", "scope": "moby", "top": "nope", - "global": map[string]interface{}{ - "nested2": map[string]interface{}{"l0": "moby"}, + "global": map[string]any{ + "nested2": map[string]any{"l0": "moby"}, }, }, }, withDeps(&chart.Chart{ Metadata: &chart.Metadata{Name: "pequod"}, - Values: map[string]interface{}{ + Values: map[string]any{ "name": "pequod", "scope": "pequod", - "global": map[string]interface{}{ - "nested2": map[string]interface{}{"l1": "pequod"}, + "global": map[string]any{ + "nested2": map[string]any{"l1": "pequod"}, }, }, }, &chart.Chart{ Metadata: &chart.Metadata{Name: "ahab"}, - Values: map[string]interface{}{ - "global": map[string]interface{}{ - "nested": map[string]interface{}{"foo": "bar"}, - "nested2": map[string]interface{}{"l2": "ahab"}, + Values: map[string]any{ + "global": map[string]any{ + "nested": map[string]any{"foo": "bar"}, + "nested2": map[string]any{"l2": "ahab"}, }, "scope": "ahab", "name": "ahab", "boat": true, - "nested": map[string]interface{}{"foo": false, "bar": true}, + "nested": map[string]any{"foo": false, "bar": true}, }, }, ), &chart.Chart{ Metadata: &chart.Metadata{Name: "spouter"}, - Values: map[string]interface{}{ + Values: map[string]any{ "scope": "spouter", - "global": map[string]interface{}{ - "nested2": map[string]interface{}{"l1": "spouter"}, + "global": map[string]any{ + "nested2": map[string]any{"l1": "spouter"}, }, }, }, @@ -196,16 +196,16 @@ func TestCoalesceValues(t *testing.T) { } } - if _, ok := v["nested"].(map[string]interface{})["boat"]; ok { + if _, ok := v["nested"].(map[string]any)["boat"]; ok { t.Error("Expected nested boat key to be removed, still present") } - subchart := v["pequod"].(map[string]interface{})["ahab"].(map[string]interface{}) + subchart := v["pequod"].(map[string]any)["ahab"].(map[string]any) if _, ok := subchart["boat"]; ok { t.Error("Expected subchart boat key to be removed, still present") } - if _, ok := subchart["nested"].(map[string]interface{})["bar"]; ok { + if _, ok := subchart["nested"].(map[string]any)["bar"]; ok { t.Error("Expected subchart nested bar key to be removed, still present") } @@ -214,28 +214,28 @@ func TestCoalesceValues(t *testing.T) { } func TestCoalesceTables(t *testing.T) { - dst := map[string]interface{}{ + dst := map[string]any{ "name": "Ishmael", - "address": map[string]interface{}{ + "address": map[string]any{ "street": "123 Spouter Inn Ct.", "city": "Nantucket", "country": nil, }, - "details": map[string]interface{}{ + "details": map[string]any{ "friends": []string{"Tashtego"}, }, "boat": "pequod", "hole": nil, } - src := map[string]interface{}{ + src := map[string]any{ "occupation": "whaler", - "address": map[string]interface{}{ + "address": map[string]any{ "state": "MA", "street": "234 Spouter Inn Ct.", "country": "US", }, "details": "empty", - "boat": map[string]interface{}{ + "boat": map[string]any{ "mast": true, }, "hole": "black", @@ -252,7 +252,7 @@ func TestCoalesceTables(t *testing.T) { t.Errorf("Unexpected occupation: %s", dst["occupation"]) } - addr, ok := dst["address"].(map[string]interface{}) + addr, ok := dst["address"].(map[string]any) if !ok { t.Fatal("Address went away.") } @@ -273,7 +273,7 @@ func TestCoalesceTables(t *testing.T) { t.Error("The country is not left out.") } - if det, ok := dst["details"].(map[string]interface{}); !ok { + if det, ok := dst["details"].(map[string]any); !ok { t.Fatalf("Details is the wrong type: %v", dst["details"]) } else if _, ok := det["friends"]; !ok { t.Error("Could not find your friends. Maybe you don't have any. :-(") @@ -287,14 +287,14 @@ func TestCoalesceTables(t *testing.T) { t.Error("The hole still exists.") } - dst2 := map[string]interface{}{ + dst2 := map[string]any{ "name": "Ishmael", - "address": map[string]interface{}{ + "address": map[string]any{ "street": "123 Spouter Inn Ct.", "city": "Nantucket", "country": "US", }, - "details": map[string]interface{}{ + "details": map[string]any{ "friends": []string{"Tashtego"}, }, "boat": "pequod", @@ -309,7 +309,7 @@ func TestCoalesceTables(t *testing.T) { t.Errorf("Unexpected name: %s", dst2["name"]) } - addr2, ok := dst2["address"].(map[string]interface{}) + addr2, ok := dst2["address"].(map[string]any) if !ok { t.Fatal("Address went away.") } @@ -326,7 +326,7 @@ func TestCoalesceTables(t *testing.T) { t.Errorf("Unexpected Country: %v", addr2["country"]) } - if det2, ok := dst2["details"].(map[string]interface{}); !ok { + if det2, ok := dst2["details"].(map[string]any); !ok { t.Fatalf("Details is the wrong type: %v", dst2["details"]) } else if _, ok := det2["friends"]; !ok { t.Error("Could not find your friends. Maybe you don't have any. :-(") @@ -345,24 +345,24 @@ func TestCoalesceValuesWarnings(t *testing.T) { c := withDeps(&chart.Chart{ Metadata: &chart.Metadata{Name: "level1"}, - Values: map[string]interface{}{ + Values: map[string]any{ "name": "moby", }, }, withDeps(&chart.Chart{ Metadata: &chart.Metadata{Name: "level2"}, - Values: map[string]interface{}{ + Values: map[string]any{ "name": "pequod", }, }, &chart.Chart{ Metadata: &chart.Metadata{Name: "level3"}, - Values: map[string]interface{}{ + Values: map[string]any{ "name": "ahab", "boat": true, - "spear": map[string]interface{}{ + "spear": map[string]any{ "tip": true, - "sail": map[string]interface{}{ + "sail": map[string]any{ "cotton": true, }, }, @@ -371,12 +371,12 @@ func TestCoalesceValuesWarnings(t *testing.T) { ), ) - vals := map[string]interface{}{ - "level2": map[string]interface{}{ - "level3": map[string]interface{}{ - "boat": map[string]interface{}{"mast": true}, - "spear": map[string]interface{}{ - "tip": map[string]interface{}{ + vals := map[string]any{ + "level2": map[string]any{ + "level3": map[string]any{ + "boat": map[string]any{"mast": true}, + "spear": map[string]any{ + "tip": map[string]any{ "sharp": true, }, "sail": true, @@ -386,7 +386,7 @@ func TestCoalesceValuesWarnings(t *testing.T) { } warnings := make([]string, 0) - printf := func(format string, v ...interface{}) { + printf := func(format string, v ...any) { t.Logf(format, v...) warnings = append(warnings, fmt.Sprintf(format, v...)) } diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index ee7e0067b..5b663b6f7 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -531,7 +531,7 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error { return errors.Wrap(err, "reading values file") } - var m map[string]interface{} + var m map[string]any if err := yaml.Unmarshal(transform(string(b), schart.Name()), &m); err != nil { return errors.Wrap(err, "transforming values file") } diff --git a/pkg/chartutil/dependencies.go b/pkg/chartutil/dependencies.go index e01b95bf7..2e452019c 100644 --- a/pkg/chartutil/dependencies.go +++ b/pkg/chartutil/dependencies.go @@ -115,7 +115,7 @@ func getAliasDependency(charts []*chart.Chart, dep *chart.Dependency) *chart.Cha } // 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 } @@ -198,20 +198,20 @@ 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 } return set(parsePath(path), data) } -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 } @@ -226,13 +226,13 @@ func processImportValues(c *chart.Chart) 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 := iv["child"].(string) parent := iv["parent"].(string) diff --git a/pkg/chartutil/dependencies_test.go b/pkg/chartutil/dependencies_test.go index 7f5e74956..8ef53f0c5 100644 --- a/pkg/chartutil/dependencies_test.go +++ b/pkg/chartutil/dependencies_test.go @@ -62,7 +62,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 diff --git a/pkg/chartutil/jsonschema.go b/pkg/chartutil/jsonschema.go index 7b9768fd3..6eb3567a6 100644 --- a/pkg/chartutil/jsonschema.go +++ b/pkg/chartutil/jsonschema.go @@ -29,7 +29,7 @@ import ( ) // ValidateAgainstSchema checks that values does not violate the structure laid out in schema -func ValidateAgainstSchema(chrt *chart.Chart, values map[string]interface{}) error { +func ValidateAgainstSchema(chrt *chart.Chart, values map[string]any) error { var sb strings.Builder if chrt.Schema != nil { err := ValidateAgainstSingleSchema(values, chrt.Schema) @@ -41,7 +41,7 @@ func ValidateAgainstSchema(chrt *chart.Chart, values map[string]interface{}) err // For each dependency, recursively call this function with the coalesced values for _, subchart := range chrt.Dependencies() { - subchartValues := values[subchart.Name()].(map[string]interface{}) + subchartValues := values[subchart.Name()].(map[string]any) if err := ValidateAgainstSchema(subchart, subchartValues); err != nil { sb.WriteString(err.Error()) } diff --git a/pkg/chartutil/jsonschema_test.go b/pkg/chartutil/jsonschema_test.go index 7610db337..a79e51b83 100644 --- a/pkg/chartutil/jsonschema_test.go +++ b/pkg/chartutil/jsonschema_test.go @@ -119,9 +119,9 @@ func TestValidateAgainstSchema(t *testing.T) { } chrt.AddDependency(subchart) - vals := map[string]interface{}{ + vals := map[string]any{ "name": "John", - "subchart": map[string]interface{}{ + "subchart": map[string]any{ "age": 25, }, } @@ -146,9 +146,9 @@ func TestValidateAgainstSchemaNegative(t *testing.T) { } chrt.AddDependency(subchart) - vals := map[string]interface{}{ + vals := map[string]any{ "name": "John", - "subchart": map[string]interface{}{}, + "subchart": map[string]any{}, } var errString string diff --git a/pkg/chartutil/save_test.go b/pkg/chartutil/save_test.go index 6914cd200..8aae89d1f 100644 --- a/pkg/chartutil/save_test.go +++ b/pkg/chartutil/save_test.go @@ -136,7 +136,7 @@ func TestSavePreservesTimestamps(t *testing.T) { Name: "ahab", Version: "1.2.3", }, - Values: map[string]interface{}{ + Values: map[string]any{ "imageName": "testimage", "imageId": 42, }, diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 2fa2bdabb..efcd05d5a 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -32,7 +32,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,12 +64,12 @@ func (v Values) Table(name string) (Values, error) { return table, err } -// AsMap is a utility function for converting Values to a map[string]interface{}. +// AsMap is a utility function for converting Values to a map[string]any. // // 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 } @@ -89,12 +89,12 @@ 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 } // This catches a case where a value is of type Values, but doesn't (for some - // reason) match the map[string]interface{}. This has been observed in the + // reason) match the map[string]any. This has been observed in the // wild, and might be a result of a nil map of type Values. if vv, ok := v2.(Values); ok { return vv, nil @@ -116,7 +116,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) } @@ -134,14 +134,14 @@ type ReleaseOptions struct { // ToRenderValues composes the struct from the data coming from the Releases, Charts and Values files // // This takes both ReleaseOptions and Capabilities to merge into the render values. -func ToRenderValues(chrt *chart.Chart, chrtVals map[string]interface{}, options ReleaseOptions, caps *Capabilities) (Values, error) { +func ToRenderValues(chrt *chart.Chart, chrtVals map[string]any, options ReleaseOptions, caps *Capabilities) (Values, error) { if caps == nil { caps = DefaultCapabilities } - top := map[string]interface{}{ + top := map[string]any{ "Chart": chrt.Metadata, "Capabilities": caps, - "Release": map[string]interface{}{ + "Release": map[string]any{ "Name": options.Name, "Namespace": options.Namespace, "IsUpgrade": options.IsUpgrade, @@ -166,8 +166,8 @@ func ToRenderValues(chrt *chart.Chart, chrtVals map[string]interface{}, options } // 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 } @@ -178,14 +178,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]]) { diff --git a/pkg/chartutil/values_test.go b/pkg/chartutil/values_test.go index c95fa503a..59476997a 100644 --- a/pkg/chartutil/values_test.go +++ b/pkg/chartutil/values_test.go @@ -68,17 +68,17 @@ water: func TestToRenderValues(t *testing.T) { - chartValues := map[string]interface{}{ + chartValues := map[string]any{ "name": "al Rashid", - "where": map[string]interface{}{ + "where": map[string]any{ "city": "Basrah", "title": "caliph", }, } - overrideValues := map[string]interface{}{ + overrideValues := map[string]any{ "name": "Haroun", - "where": map[string]interface{}{ + "where": map[string]any{ "city": "Baghdad", "date": "809 CE", }, @@ -112,7 +112,7 @@ func TestToRenderValues(t *testing.T) { if name := res["Chart"].(*chart.Metadata).Name; name != "test" { t.Errorf("Expected chart name 'test', got %q", name) } - relmap := res["Release"].(map[string]interface{}) + relmap := res["Release"].(map[string]any) if name := relmap["Name"]; name.(string) != "Seven Voyages" { t.Errorf("Expected release name 'Seven Voyages', got %q", name) } @@ -139,7 +139,7 @@ func TestToRenderValues(t *testing.T) { if vals["name"] != "Haroun" { t.Errorf("Expected 'Haroun', got %q (%v)", vals["name"], vals) } - where := vals["where"].(map[string]interface{}) + where := vals["where"].(map[string]any) expects := map[string]string{ "city": "Baghdad", "date": "809 CE", @@ -223,7 +223,7 @@ chapter: } } -func matchValues(t *testing.T, data map[string]interface{}) { +func matchValues(t *testing.T, data map[string]any) { if data["poet"] != "Coleridge" { t.Errorf("Unexpected poet: %s", data["poet"]) } @@ -247,7 +247,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) diff --git a/pkg/cli/output/output.go b/pkg/cli/output/output.go index a46c977ad..363fdb7f2 100644 --- a/pkg/cli/output/output.go +++ b/pkg/cli/output/output.go @@ -103,7 +103,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 { @@ -114,7 +114,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 errors.Wrap(err, "unable to write YAML output") diff --git a/pkg/cli/values/options.go b/pkg/cli/values/options.go index 7fb1339f9..b1aaa1024 100644 --- a/pkg/cli/values/options.go +++ b/pkg/cli/values/options.go @@ -40,12 +40,12 @@ type Options struct { // MergeValues merges values from files specified via -f/--values and directly // via --set-json, --set, --set-string, or --set-file, marshaling them to YAML -func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, error) { - base := map[string]interface{}{} +func (opts *Options) MergeValues(p getter.Providers) (map[string]any, error) { + base := map[string]any{} // User specified a values files via -f/--values for _, filePath := range opts.ValueFiles { - currentMap := map[string]interface{}{} + currentMap := map[string]any{} bytes, err := readFile(filePath, p) if err != nil { @@ -82,7 +82,7 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er // User specified a value via --set-file for _, value := range opts.FileValues { - reader := func(rs []rune) (interface{}, error) { + reader := func(rs []rune) (any, error) { bytes, err := readFile(string(rs), p) if err != nil { return nil, err @@ -97,15 +97,15 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er return base, nil } -func mergeMaps(a, b map[string]interface{}) map[string]interface{} { - out := make(map[string]interface{}, len(a)) +func mergeMaps(a, b map[string]any) map[string]any { + out := make(map[string]any, len(a)) for k, v := range a { out[k] = v } for k, v := range b { - if v, ok := v.(map[string]interface{}); ok { + if v, ok := v.(map[string]any); ok { if bv, ok := out[k]; ok { - if bv, ok := bv.(map[string]interface{}); ok { + if bv, ok := bv.(map[string]any); ok { out[k] = mergeMaps(bv, v) continue } diff --git a/pkg/cli/values/options_test.go b/pkg/cli/values/options_test.go index 54124c0fa..e745e9fcb 100644 --- a/pkg/cli/values/options_test.go +++ b/pkg/cli/values/options_test.go @@ -24,24 +24,24 @@ import ( ) func TestMergeValues(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", } @@ -64,7 +64,7 @@ func TestMergeValues(t *testing.T) { } testMap = mergeMaps(anotherFlatMap, anotherNestedMap) - expectedMap := map[string]interface{}{ + expectedMap := map[string]any{ "testing": "fun", "foo": "bar", "baz": map[string]string{ diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 657d5767b..a2b9a33de 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -118,7 +118,7 @@ func (e Engine) initFunMap(t *template.Template, referenceTpls map[string]render includedNames := make(map[string]int) // Add the 'include' function here so we can close over t. - funcMap["include"] = func(name string, data interface{}) (string, error) { + funcMap["include"] = func(name string, data any) (string, error) { var buf strings.Builder if v, ok := includedNames[name]; ok { if v > recursionMaxNums { @@ -161,7 +161,7 @@ func (e Engine) initFunMap(t *template.Template, referenceTpls map[string]render } // 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 @@ -361,14 +361,14 @@ func allTemplates(c *chart.Chart, vals chartutil.Values) map[string]renderable { // // As it recurses, it also sets the values to be appropriate for the template // scope. -func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil.Values) map[string]interface{} { - subCharts := make(map[string]interface{}) +func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil.Values) map[string]any { + subCharts := make(map[string]any) chartMetaData := struct { chart.Metadata IsRoot bool }{*c.Metadata, c.IsRoot()} - next := map[string]interface{}{ + next := map[string]any{ "Chart": chartMetaData, "Files": newFiles(c.Files), "Release": vals["Release"], diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index 434b939dc..6e1674f27 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -92,14 +92,14 @@ func TestRender(t *testing.T) { {Name: "templates/test4", Data: []byte("{{toJson .Values}}")}, {Name: "templates/test5", 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", }, }, @@ -212,11 +212,11 @@ func TestRenderWIthDNS(t *testing.T) { Templates: []*chart.File{ {Name: "templates/test1", 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 := chartutil.CoalesceValues(c, vals) @@ -250,7 +250,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) @@ -267,7 +267,7 @@ func TestParallelRenderInternals(t *testing.T) { } func TestParseErrors(t *testing.T) { - vals := chartutil.Values{"Values": map[string]interface{}{}} + vals := chartutil.Values{"Values": map[string]any{}} tplsUndefinedFunction := map[string]renderable{ "undefined_function": {tpl: `{{foo}}`, vals: vals}, @@ -283,7 +283,7 @@ func TestParseErrors(t *testing.T) { } func TestExecErrors(t *testing.T) { - vals := chartutil.Values{"Values": map[string]interface{}{}} + vals := chartutil.Values{"Values": map[string]any{}} cases := []struct { name string tpls map[string]renderable @@ -347,7 +347,7 @@ linebreak`, } func TestFailErrors(t *testing.T) { - vals := chartutil.Values{"Values": map[string]interface{}{}} + vals := chartutil.Values{"Values": map[string]any{}} failtpl := `All your base are belong to us{{ fail "This is an error" }}` tplsFailed := map[string]renderable{ @@ -452,7 +452,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) } @@ -483,7 +483,7 @@ func TestRenderNestedValues(t *testing.T) { {Name: deepestpath, Data: []byte(`And this same {{.Values.what}} that smiles {{.Values.global.when}}`)}, {Name: checkrelease, 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{ @@ -491,7 +491,7 @@ func TestRenderNestedValues(t *testing.T) { Templates: []*chart.File{ {Name: innerpath, 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) @@ -501,10 +501,10 @@ func TestRenderNestedValues(t *testing.T) { {Name: outerpath, Data: []byte(`Gather ye {{.Values.what}} while ye may`)}, {Name: subchartspath, 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", }, @@ -512,15 +512,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", }, } diff --git a/pkg/engine/funcs.go b/pkg/engine/funcs.go index 8f05a3a1d..dd3480963 100644 --- a/pkg/engine/funcs.go +++ b/pkg/engine/funcs.go @@ -58,13 +58,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 }, } @@ -79,7 +79,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. @@ -88,14 +88,14 @@ func toYAML(v interface{}) string { return strings.TrimSuffix(string(data), "\n") } -// fromYAML converts a YAML document into a map[string]interface{}. +// fromYAML converts a YAML document into a map[string]any. // // This is not a general-purpose YAML parser, and will not parse all valid // 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() @@ -103,17 +103,17 @@ func fromYAML(str string) map[string]interface{} { return m } -// fromYAMLArray converts a YAML array into a []interface{}. +// fromYAMLArray converts a YAML array into a []any. // // This is not a general-purpose YAML parser, and will not parse all valid // 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 } @@ -122,7 +122,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) @@ -136,7 +136,7 @@ func toTOML(v interface{}) string { // 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. @@ -145,14 +145,14 @@ func toJSON(v interface{}) string { return string(data) } -// fromJSON converts a JSON document into a map[string]interface{}. +// fromJSON converts a JSON document into a map[string]any. // // This is not a general-purpose JSON parser, and will not parse all valid // 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() @@ -160,17 +160,17 @@ func fromJSON(str string) map[string]interface{} { return m } -// fromJSONArray converts a JSON array into a []interface{}. +// fromJSONArray converts a JSON array into a []any. // // This is not a general-purpose JSON parser, and will not parse all valid // 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 } diff --git a/pkg/engine/funcs_test.go b/pkg/engine/funcs_test.go index 29bc121b5..dc08e58a8 100644 --- a/pkg/engine/funcs_test.go +++ b/pkg/engine/funcs_test.go @@ -28,19 +28,19 @@ func TestFuncs(t *testing.T) { //TODO write tests for failure cases tests := []struct { tpl, expect string - vars interface{} + vars any }{{ tpl: `{{ toYaml . }}`, expect: `foo: bar`, - vars: map[string]interface{}{"foo": "bar"}, + vars: map[string]any{"foo": "bar"}, }, { tpl: `{{ toToml . }}`, expect: "foo = \"bar\"\n", - vars: map[string]interface{}{"foo": "bar"}, + vars: map[string]any{"foo": "bar"}, }, { tpl: `{{ toJson . }}`, expect: `{"foo":"bar"}`, - vars: map[string]interface{}{"foo": "bar"}, + vars: map[string]any{"foo": "bar"}, }, { tpl: `{{ fromYaml . }}`, expect: "map[hello:world]", @@ -81,11 +81,11 @@ func TestFuncs(t *testing.T) { }, { tpl: `{{ merge .dict (fromYaml .yaml) }}`, expect: `map[a:map[b:c]]`, - vars: map[string]interface{}{"dict": map[string]interface{}{"a": map[string]interface{}{"b": "c"}}, "yaml": `{"a":{"b":"d"}}`}, + vars: map[string]any{"dict": map[string]any{"a": map[string]any{"b": "c"}}, "yaml": `{"a":{"b":"d"}}`}, }, { tpl: `{{ merge (fromYaml .yaml) .dict }}`, expect: `map[a:map[b:d]]`, - vars: map[string]interface{}{"dict": map[string]interface{}{"a": map[string]interface{}{"b": "c"}}, "yaml": `{"a":{"b":"d"}}`}, + vars: map[string]any{"dict": map[string]any{"a": map[string]any{"b": "c"}}, "yaml": `{"a":{"b":"d"}}`}, }, { tpl: `{{ fromYaml . }}`, expect: `map[Error:error unmarshaling JSON: while decoding JSON: json: cannot unmarshal array into Go value of type map[string]interface {}]`, @@ -121,34 +121,34 @@ func TestFuncs(t *testing.T) { // be used to accidentally update mergo. This test and message should catch // the problem and explain why it's happening. func TestMerge(t *testing.T) { - dict := map[string]interface{}{ - "src2": map[string]interface{}{ + dict := map[string]any{ + "src2": map[string]any{ "h": 10, "i": "i", "j": "j", }, - "src1": map[string]interface{}{ + "src1": map[string]any{ "a": 1, "b": 2, - "d": map[string]interface{}{ + "d": map[string]any{ "e": "four", }, "g": []int{6, 7}, "i": "aye", "j": "jay", - "k": map[string]interface{}{ + "k": map[string]any{ "l": false, }, }, - "dst": map[string]interface{}{ + "dst": map[string]any{ "a": "one", "c": 3, - "d": map[string]interface{}{ + "d": map[string]any{ "f": 5, }, "g": []int{8, 9}, "i": "eye", - "k": map[string]interface{}{ + "k": map[string]any{ "l": true, }, }, @@ -158,11 +158,11 @@ func TestMerge(t *testing.T) { err := template.Must(template.New("test").Funcs(funcMap()).Parse(tpl)).Execute(&b, dict) assert.NoError(t, err) - expected := map[string]interface{}{ + expected := map[string]any{ "a": "one", // key overridden "b": 2, // merged from src1 "c": 3, // merged from dst - "d": map[string]interface{}{ // deep merge + "d": map[string]any{ // deep merge "e": "four", "f": 5, }, @@ -170,7 +170,7 @@ func TestMerge(t *testing.T) { "h": 10, // merged from src2 "i": "eye", // overridden twice "j": "jay", // overridden and merged - "k": map[string]interface{}{ + "k": map[string]any{ "l": true, // overridden }, } diff --git a/pkg/engine/lookup_func.go b/pkg/engine/lookup_func.go index b378ca9d6..dc1b56098 100644 --- a/pkg/engine/lookup_func.go +++ b/pkg/engine/lookup_func.go @@ -30,7 +30,7 @@ import ( "k8s.io/client-go/rest" ) -type lookupFunc = func(apiversion string, resource string, namespace string, name string) (map[string]interface{}, error) +type lookupFunc = func(apiversion string, resource string, namespace string, name string) (map[string]any, error) // NewLookupFunction returns a function for looking up objects in the cluster. // @@ -39,11 +39,11 @@ type lookupFunc = func(apiversion string, resource string, namespace string, nam // This function is considered deprecated, and will be renamed in Helm 4. It will no // longer be a public function. func NewLookupFunction(config *rest.Config) lookupFunc { - return func(apiversion string, resource string, namespace string, name string) (map[string]interface{}, error) { + return func(apiversion string, resource string, namespace string, name string) (map[string]any, error) { var client dynamic.ResourceInterface c, namespaced, err := getDynamicClientOnKind(apiversion, resource, config) if err != nil { - return map[string]interface{}{}, err + return map[string]any{}, err } if namespaced && namespace != "" { client = c.Namespace(namespace) @@ -57,9 +57,9 @@ func NewLookupFunction(config *rest.Config) lookupFunc { if apierrors.IsNotFound(err) { // Just return an empty interface when the object was not found. // That way, users can use `if not (lookup ...)` in their templates. - return map[string]interface{}{}, nil + return map[string]any{}, nil } - return map[string]interface{}{}, err + return map[string]any{}, err } return obj.UnstructuredContent(), nil } @@ -69,9 +69,9 @@ func NewLookupFunction(config *rest.Config) lookupFunc { if apierrors.IsNotFound(err) { // Just return an empty interface when the object was not found. // That way, users can use `if not (lookup ...)` in their templates. - return map[string]interface{}{}, nil + return map[string]any{}, nil } - return map[string]interface{}{}, err + return map[string]any{}, err } return obj.UnstructuredContent(), nil } diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 1ab59f25d..80d81a178 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -70,7 +70,7 @@ var ManagedFieldsManager string // Client represents a client capable of communicating with the Kubernetes API. type Client struct { Factory Factory - Log func(string, ...interface{}) + Log func(string, ...any) // Namespace allows to bypass the kubeconfig file for the choice of the namespace Namespace string @@ -100,7 +100,7 @@ func New(getter genericclioptions.RESTClientGetter) *Client { } } -var nopLogger = func(_ string, _ ...interface{}) {} +var nopLogger = func(_ string, _ ...any) {} // getKubeClient get or create a new KubernetesClientSet func (c *Client) getKubeClient() (*kubernetes.Clientset, error) { diff --git a/pkg/kube/ready.go b/pkg/kube/ready.go index bdad3af08..80a8ac7dd 100644 --- a/pkg/kube/ready.go +++ b/pkg/kube/ready.go @@ -59,7 +59,7 @@ func CheckJobs(checkJobs bool) ReadyCheckerOption { // NewReadyChecker creates a new checker. Passed ReadyCheckerOptions can // be used to override defaults. -func NewReadyChecker(cl kubernetes.Interface, log func(string, ...interface{}), opts ...ReadyCheckerOption) ReadyChecker { +func NewReadyChecker(cl kubernetes.Interface, log func(string, ...any), opts ...ReadyCheckerOption) ReadyChecker { c := ReadyChecker{ client: cl, log: log, @@ -76,7 +76,7 @@ func NewReadyChecker(cl kubernetes.Interface, log func(string, ...interface{}), // ReadyChecker is a type that can check core Kubernetes types for readiness. type ReadyChecker struct { client kubernetes.Interface - log func(string, ...interface{}) + log func(string, ...any) checkJobs bool pausedAsReady bool } diff --git a/pkg/kube/wait.go b/pkg/kube/wait.go index 8928d6745..4b233ae40 100644 --- a/pkg/kube/wait.go +++ b/pkg/kube/wait.go @@ -39,7 +39,7 @@ import ( type waiter struct { c ReadyChecker timeout time.Duration - log func(string, ...interface{}) + log func(string, ...any) } // waitForResources polls to get the current status of all pods, PVCs, Services and diff --git a/pkg/lint/lint.go b/pkg/lint/lint.go index 67e76bd3d..e10717a53 100644 --- a/pkg/lint/lint.go +++ b/pkg/lint/lint.go @@ -24,7 +24,7 @@ import ( ) // All runs all of the available linters on the given base directory. -func All(basedir string, values map[string]interface{}, namespace string, strict bool) support.Linter { +func All(basedir string, values map[string]any, namespace string, strict bool) support.Linter { // Using abs path to get directory context chartDir, _ := filepath.Abs(basedir) diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 0e5d42391..b9cddc1d0 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -24,7 +24,7 @@ import ( "helm.sh/helm/v3/pkg/lint/support" ) -var values map[string]interface{} +var values map[string]any const namespace = "testNamespace" const strict = false diff --git a/pkg/lint/rules/chartfile.go b/pkg/lint/rules/chartfile.go index 70532ad4f..332a53ccb 100644 --- a/pkg/lint/rules/chartfile.go +++ b/pkg/lint/rules/chartfile.go @@ -66,15 +66,15 @@ func Chartfile(linter *support.Linter) { linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartDependencies(chartFile)) } -func validateChartVersionType(data map[string]interface{}) error { +func validateChartVersionType(data map[string]any) error { return isStringValue(data, "version") } -func validateChartAppVersionType(data map[string]interface{}) error { +func validateChartAppVersionType(data map[string]any) error { return isStringValue(data, "appVersion") } -func isStringValue(data map[string]interface{}, key string) error { +func isStringValue(data map[string]any, key string) error { value, ok := data[key] if !ok { return nil @@ -196,14 +196,14 @@ func validateChartType(cf *chart.Metadata) error { } // loadChartFileForTypeCheck loads the Chart.yaml -// in a generic form of a map[string]interface{}, so that the type +// in a generic form of a map[string]any, so that the type // of the values can be checked -func loadChartFileForTypeCheck(filename string) (map[string]interface{}, error) { +func loadChartFileForTypeCheck(filename string) (map[string]any, error) { b, err := os.ReadFile(filename) if err != nil { return nil, err } - y := make(map[string]interface{}) + y := make(map[string]any) err = yaml.Unmarshal(b, &y) return y, err } diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index 61425f92e..23be84b6d 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -45,7 +45,7 @@ var ( ) // Templates lints the templates in the Linter. -func Templates(linter *support.Linter, values map[string]interface{}, namespace string, strict bool) { +func Templates(linter *support.Linter, values map[string]any, namespace string, strict bool) { fpath := "templates/" templatesPath := filepath.Join(linter.ChartDir, fpath) diff --git a/pkg/lint/rules/template_test.go b/pkg/lint/rules/template_test.go index f3aa641f2..42445be3e 100644 --- a/pkg/lint/rules/template_test.go +++ b/pkg/lint/rules/template_test.go @@ -48,7 +48,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" const strict = false @@ -266,7 +266,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", }, diff --git a/pkg/lint/rules/values.go b/pkg/lint/rules/values.go index 538d8381b..6b7f8c038 100644 --- a/pkg/lint/rules/values.go +++ b/pkg/lint/rules/values.go @@ -30,7 +30,7 @@ import ( // // This function is deprecated and will be removed in Helm 4. func Values(linter *support.Linter) { - ValuesWithOverrides(linter, map[string]interface{}{}) + ValuesWithOverrides(linter, map[string]any{}) } // ValuesWithOverrides tests the values.yaml file. @@ -39,7 +39,7 @@ func Values(linter *support.Linter) { // they are only tested for well-formedness. // // If additional values are supplied, they are coalesced into the values in values.yaml. -func ValuesWithOverrides(linter *support.Linter, values map[string]interface{}) { +func ValuesWithOverrides(linter *support.Linter, values map[string]any) { file := "values.yaml" vf := filepath.Join(linter.ChartDir, file) fileExists := linter.RunLinterRule(support.InfoSev, file, validateValuesFileExistence(vf)) @@ -59,7 +59,7 @@ func validateValuesFileExistence(valuesPath string) error { return nil } -func validateValuesFile(valuesPath string, overrides map[string]interface{}) error { +func validateValuesFile(valuesPath string, overrides map[string]any) error { values, err := chartutil.ReadValuesFile(valuesPath) if err != nil { return errors.Wrap(err, "unable to parse YAML") @@ -70,7 +70,7 @@ func validateValuesFile(valuesPath string, overrides map[string]interface{}) err // We could change that. For now, though, we retain that strategy, and thus can // coalesce tables (like reuse-values does) instead of doing the full chart // CoalesceValues - coalescedValues := chartutil.CoalesceTables(make(map[string]interface{}, len(overrides)), overrides) + coalescedValues := chartutil.CoalesceTables(make(map[string]any, len(overrides)), overrides) coalescedValues = chartutil.CoalesceTables(coalescedValues, values) ext := filepath.Ext(valuesPath) diff --git a/pkg/lint/rules/values_test.go b/pkg/lint/rules/values_test.go index 21eb875f4..901be9041 100644 --- a/pkg/lint/rules/values_test.go +++ b/pkg/lint/rules/values_test.go @@ -68,7 +68,7 @@ func TestValidateValuesFileWellFormed(t *testing.T) { tmpdir := ensure.TempFile(t, "values.yaml", []byte(badYaml)) defer os.RemoveAll(tmpdir) valfile := filepath.Join(tmpdir, "values.yaml") - if err := validateValuesFile(valfile, map[string]interface{}{}); err == nil { + if err := validateValuesFile(valfile, map[string]any{}); err == nil { t.Fatal("expected values file to fail parsing") } } @@ -80,7 +80,7 @@ func TestValidateValuesFileSchema(t *testing.T) { createTestingSchema(t, tmpdir) valfile := filepath.Join(tmpdir, "values.yaml") - if err := validateValuesFile(valfile, map[string]interface{}{}); err != nil { + if err := validateValuesFile(valfile, map[string]any{}); err != nil { t.Fatalf("Failed validation with %s", err) } } @@ -94,7 +94,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) { valfile := filepath.Join(tmpdir, "values.yaml") - err := validateValuesFile(valfile, map[string]interface{}{}) + err := validateValuesFile(valfile, map[string]any{}) if err == nil { t.Fatal("expected values file to fail parsing") } @@ -104,7 +104,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) { func TestValidateValuesFileSchemaOverrides(t *testing.T) { yaml := "username: admin" - overrides := map[string]interface{}{ + overrides := map[string]any{ "password": "swordfish", } tmpdir := ensure.TempFile(t, "values.yaml", []byte(yaml)) @@ -121,24 +121,24 @@ func TestValidateValuesFile(t *testing.T) { tests := []struct { name string yaml string - overrides map[string]interface{} + overrides map[string]any errorMessage string }{ { name: "value added", yaml: "username: admin", - overrides: map[string]interface{}{"password": "swordfish"}, + overrides: map[string]any{"password": "swordfish"}, }, { name: "value not overridden", yaml: "username: admin\npassword:", - overrides: map[string]interface{}{"username": "anotherUser"}, + overrides: map[string]any{"username": "anotherUser"}, errorMessage: "Expected: string, given: null", }, { name: "value overridden", yaml: "username: admin\npassword:", - overrides: map[string]interface{}{"username": "anotherUser", "password": "swordfish"}, + overrides: map[string]any{"username": "anotherUser", "password": "swordfish"}, }, } diff --git a/pkg/plugin/installer/installer.go b/pkg/plugin/installer/installer.go index 6f01494e5..e9fce017a 100644 --- a/pkg/plugin/installer/installer.go +++ b/pkg/plugin/installer/installer.go @@ -128,7 +128,7 @@ func isPlugin(dirname string) bool { var logger = log.New(os.Stderr, "[debug] ", log.Lshortfile) -func debug(format string, args ...interface{}) { +func debug(format string, args ...any) { if Debug { logger.Output(2, fmt.Sprintf(format, args...)) } diff --git a/pkg/registry/utils_test.go b/pkg/registry/utils_test.go index aaabffde3..3d1a1dcd2 100644 --- a/pkg/registry/utils_test.go +++ b/pkg/registry/utils_test.go @@ -142,7 +142,7 @@ func setup(suite *TestSuite, tlsEnabled bool, insecure bool) *registry.Registry config.HTTP.Addr = fmt.Sprintf(":%d", port) // config.HTTP.Addr = fmt.Sprintf("127.0.0.1:%d", port) config.HTTP.DrainTimeout = time.Duration(10) * time.Second - config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + config.Storage = map[string]configuration.Parameters{"inmemory": map[string]any{}} config.Auth = configuration.Auth{ "htpasswd": configuration.Parameters{ "realm": "localhost", diff --git a/pkg/release/mock.go b/pkg/release/mock.go index a28e1dc16..1598a062b 100644 --- a/pkg/release/mock.go +++ b/pkg/release/mock.go @@ -98,7 +98,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{ diff --git a/pkg/release/release.go b/pkg/release/release.go index b90612873..d4bfcda53 100644 --- a/pkg/release/release.go +++ b/pkg/release/release.go @@ -28,7 +28,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. diff --git a/pkg/releaseutil/kind_sorter.go b/pkg/releaseutil/kind_sorter.go index 1d1874cfa..1bd3c36b4 100644 --- a/pkg/releaseutil/kind_sorter.go +++ b/pkg/releaseutil/kind_sorter.go @@ -130,7 +130,7 @@ func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.H return h } -func lessByKind(a interface{}, b interface{}, kindA string, kindB string, o KindSortOrder) bool { +func lessByKind(a any, b any, kindA string, kindB string, o KindSortOrder) bool { ordering := make(map[string]int, len(o)) for v, k := range o { ordering[k] = v diff --git a/pkg/repo/index.go b/pkg/repo/index.go index ba2e365c8..10d6bb9b0 100644 --- a/pkg/repo/index.go +++ b/pkg/repo/index.go @@ -80,7 +80,7 @@ func (c ChartVersions) Less(a, b int) bool { // IndexFile represents the index file in a chart repository type IndexFile struct { // This is used ONLY for validation against chartmuseum's index files and is discarded after validation. - ServerInfo map[string]interface{} `json:"serverInfo,omitempty"` + ServerInfo map[string]any `json:"serverInfo,omitempty"` APIVersion string `json:"apiVersion"` Generated time.Time `json:"generated"` Entries map[string]ChartVersions `json:"entries"` diff --git a/pkg/repo/repotest/server.go b/pkg/repo/repotest/server.go index 031892fc4..bfb9ed1bb 100644 --- a/pkg/repo/repotest/server.go +++ b/pkg/repo/repotest/server.go @@ -115,7 +115,7 @@ func NewOCIServer(t *testing.T, dir string) (*OCIServer, error) { config.HTTP.Addr = fmt.Sprintf(":%d", port) config.HTTP.DrainTimeout = time.Duration(10) * time.Second - config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + config.Storage = map[string]configuration.Parameters{"inmemory": map[string]any{}} config.Auth = configuration.Auth{ "htpasswd": configuration.Parameters{ "realm": "localhost", diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index a63fec011..28d5ff60a 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -42,7 +42,7 @@ const ConfigMapsDriverName = "ConfigMap" // ConfigMapsInterface. type ConfigMaps struct { impl corev1.ConfigMapInterface - Log func(string, ...interface{}) + Log func(string, ...any) } // NewConfigMaps initializes a new ConfigMaps wrapping an implementation of @@ -50,7 +50,7 @@ type ConfigMaps struct { func NewConfigMaps(impl corev1.ConfigMapInterface) *ConfigMaps { return &ConfigMaps{ impl: impl, - Log: func(_ string, _ ...interface{}) {}, + Log: func(_ string, _ ...any) {}, } } diff --git a/pkg/storage/driver/mock_test.go b/pkg/storage/driver/mock_test.go index c0236ece8..827b4fa5f 100644 --- a/pkg/storage/driver/mock_test.go +++ b/pkg/storage/driver/mock_test.go @@ -258,7 +258,7 @@ func newTestFixtureSQL(t *testing.T, releases ...*rspb.Release) (*SQL, sqlmock.S sqlxDB := sqlx.NewDb(sqlDB, "sqlmock") return &SQL{ db: sqlxDB, - Log: func(a string, b ...interface{}) {}, + Log: func(a string, b ...any) {}, namespace: "default", statementBuilder: sq.StatementBuilder.PlaceholderFormat(sq.Dollar), }, mock diff --git a/pkg/storage/driver/secrets.go b/pkg/storage/driver/secrets.go index 56df54040..4998a49b3 100644 --- a/pkg/storage/driver/secrets.go +++ b/pkg/storage/driver/secrets.go @@ -42,7 +42,7 @@ const SecretsDriverName = "Secret" // SecretsInterface. type Secrets struct { impl corev1.SecretInterface - Log func(string, ...interface{}) + Log func(string, ...any) } // NewSecrets initializes a new Secrets wrapping an implementation of @@ -50,7 +50,7 @@ type Secrets struct { func NewSecrets(impl corev1.SecretInterface) *Secrets { return &Secrets{ impl: impl, - Log: func(_ string, _ ...interface{}) {}, + Log: func(_ string, _ ...any) {}, } } diff --git a/pkg/storage/driver/sql.go b/pkg/storage/driver/sql.go index c8a6ae04f..a04364626 100644 --- a/pkg/storage/driver/sql.go +++ b/pkg/storage/driver/sql.go @@ -74,7 +74,7 @@ type SQL struct { namespace string statementBuilder sq.StatementBuilderType - Log func(string, ...interface{}) + Log func(string, ...any) } // Name returns the name of the driver. @@ -181,7 +181,7 @@ type SQLReleaseWrapper struct { } // NewSQL initializes a new sql driver. -func NewSQL(connectionString string, logger func(string, ...interface{}), namespace string) (*SQL, error) { +func NewSQL(connectionString string, logger func(string, ...any), namespace string) (*SQL, error) { db, err := sqlx.Connect(postgreSQLDialect, connectionString) if err != nil { return nil, err diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 0a18b34a0..9a960f445 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -43,7 +43,7 @@ type Storage struct { // ignored (meaning no limits are imposed). MaxHistory int - Log func(string, ...interface{}) + Log func(string, ...any) } // Get retrieves the release from storage. An error is returned @@ -261,6 +261,6 @@ func Init(d driver.Driver) *Storage { } return &Storage{ Driver: d, - Log: func(_ string, _ ...interface{}) {}, + Log: func(_ string, _ ...any) {}, } } diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 058b077e8..a41bdcf2c 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -553,7 +553,7 @@ func (test ReleaseTestData) ToRelease() *rspb.Release { } } -func assertErrNil(eh func(args ...interface{}), err error, message string) { +func assertErrNil(eh func(args ...any), err error, message string) { if err != nil { eh(fmt.Sprintf("%s: %q", message, err)) } diff --git a/pkg/strvals/parser.go b/pkg/strvals/parser.go index 2828f20c0..13facaf54 100644 --- a/pkg/strvals/parser.go +++ b/pkg/strvals/parser.go @@ -52,8 +52,8 @@ func ToYAML(s string) (string, error) { // Parse parses a set line. // // A set line is of the form name1=value1,name2=value2 -func Parse(s string) (map[string]interface{}, error) { - vals := map[string]interface{}{} +func Parse(s string) (map[string]any, error) { + vals := map[string]any{} scanner := bytes.NewBufferString(s) t := newParser(scanner, vals, false) err := t.parse() @@ -63,8 +63,8 @@ func Parse(s string) (map[string]interface{}, error) { // ParseString parses a set line and forces a string value. // // A set line is of the form name1=value1,name2=value2 -func ParseString(s string) (map[string]interface{}, error) { - vals := map[string]interface{}{} +func ParseString(s string) (map[string]any, error) { + vals := map[string]any{} scanner := bytes.NewBufferString(s) t := newParser(scanner, vals, true) err := t.parse() @@ -75,7 +75,7 @@ func ParseString(s string) (map[string]interface{}, error) { // // If the strval string has a key that exists in dest, it overwrites the // dest version. -func ParseInto(s string, dest map[string]interface{}) error { +func ParseInto(s string, dest map[string]any) error { scanner := bytes.NewBufferString(s) t := newParser(scanner, dest, false) return t.parse() @@ -87,8 +87,8 @@ func ParseInto(s string, dest map[string]interface{}) error { // // When the files at path1 and path2 contained "val1" and "val2" respectively, the set line is consumed as // name1=val1,name2=val2 -func ParseFile(s string, reader RunesValueReader) (map[string]interface{}, error) { - vals := map[string]interface{}{} +func ParseFile(s string, reader RunesValueReader) (map[string]any, error) { + vals := map[string]any{} scanner := bytes.NewBufferString(s) t := newFileParser(scanner, vals, reader) err := t.parse() @@ -98,7 +98,7 @@ func ParseFile(s string, reader RunesValueReader) (map[string]interface{}, error // ParseIntoString parses a strvals line and merges the result into dest. // // This method always returns a string as the value. -func ParseIntoString(s string, dest map[string]interface{}) error { +func ParseIntoString(s string, dest map[string]any) error { scanner := bytes.NewBufferString(s) t := newParser(scanner, dest, true) return t.parse() @@ -109,7 +109,7 @@ func ParseIntoString(s string, dest map[string]interface{}) error { // An empty val is treated as null. // // If a key exists in dest, the new value overwrites the dest version. -func ParseJSON(s string, dest map[string]interface{}) error { +func ParseJSON(s string, dest map[string]any) error { scanner := bytes.NewBufferString(s) t := newJSONParser(scanner, dest) return t.parse() @@ -118,7 +118,7 @@ func ParseJSON(s string, dest map[string]interface{}) error { // ParseIntoFile parses a filevals line and merges the result into dest. // // This method always returns a string as the value. -func ParseIntoFile(s string, dest map[string]interface{}, reader RunesValueReader) error { +func ParseIntoFile(s string, dest map[string]any, reader RunesValueReader) error { scanner := bytes.NewBufferString(s) t := newFileParser(scanner, dest, reader) return t.parse() @@ -126,7 +126,7 @@ func ParseIntoFile(s string, dest map[string]interface{}, reader RunesValueReade // RunesValueReader is a function that takes the given value (a slice of runes) // and returns the parsed value -type RunesValueReader func([]rune) (interface{}, error) +type RunesValueReader func([]rune) (any, error) // parser is a simple parser that takes a strvals line and parses it into a // map representation. @@ -135,23 +135,23 @@ type RunesValueReader func([]rune) (interface{}, error) // where data is the final parsed data from the parses with correct types type parser struct { sc *bytes.Buffer - data map[string]interface{} + data map[string]any reader RunesValueReader isjsonval bool } -func newParser(sc *bytes.Buffer, data map[string]interface{}, stringBool bool) *parser { - stringConverter := func(rs []rune) (interface{}, error) { +func newParser(sc *bytes.Buffer, data map[string]any, stringBool bool) *parser { + stringConverter := func(rs []rune) (any, error) { return typedVal(rs, stringBool), nil } return &parser{sc: sc, data: data, reader: stringConverter} } -func newJSONParser(sc *bytes.Buffer, data map[string]interface{}) *parser { +func newJSONParser(sc *bytes.Buffer, data map[string]any) *parser { return &parser{sc: sc, data: data, reader: nil, isjsonval: true} } -func newFileParser(sc *bytes.Buffer, data map[string]interface{}, reader RunesValueReader) *parser { +func newFileParser(sc *bytes.Buffer, data map[string]any, reader RunesValueReader) *parser { return &parser{sc: sc, data: data, reader: reader} } @@ -176,7 +176,7 @@ func runeSet(r []rune) map[rune]bool { return s } -func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr error) { +func (t *parser) key(data map[string]any, nestedNameLevel int) (reterr error) { defer func() { if r := recover(); r != nil { reterr = fmt.Errorf("unable to parse key: %s", r) @@ -200,9 +200,9 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e } kk := string(k) // Find or create target list - list := []interface{}{} + list := []any{} if _, ok := data[kk]; ok { - list = data[kk].([]interface{}) + list = data[kk].([]any) } // Now we need to get the value after the ]. @@ -224,7 +224,7 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e // Since Decode has its own buffer that consumes more characters (from underlying t.sc) than the ones actually decoded, // we invoke Decode on a separate reader built with a copy of what is left in t.sc. After Decode is executed, we // discard in t.sc the chars of the decoded json value (the number of those characters is returned by InputOffset). - var jsonval interface{} + var jsonval any dec := json.NewDecoder(strings.NewReader(t.sc.String())) if err = dec.Decode(&jsonval); err != nil { return err @@ -270,9 +270,9 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e } // First, create or find the target map. - inner := map[string]interface{}{} + inner := map[string]any{} if _, ok := data[string(k)]; ok { - inner = data[string(k)].(map[string]interface{}) + inner = data[string(k)].(map[string]any) } // Recurse @@ -288,7 +288,7 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e } } -func set(data map[string]interface{}, key string, val interface{}) { +func set(data map[string]any, key string, val any) { // If key is empty, don't set it. if len(key) == 0 { return @@ -296,7 +296,7 @@ func set(data map[string]interface{}, key string, val interface{}) { data[key] = val } -func setIndex(list []interface{}, index int, val interface{}) (l2 []interface{}, err error) { +func setIndex(list []any, index int, val any) (l2 []any, err error) { // There are possible index values that are out of range on a target system // causing a panic. This will catch the panic and return an error instead. // The value of the index that causes a panic varies from system to system. @@ -313,7 +313,7 @@ func setIndex(list []interface{}, index int, val interface{}) (l2 []interface{}, return list, fmt.Errorf("index of %d is greater than maximum supported index of %d", index, MaxIndex) } if len(list) <= index { - newlist := make([]interface{}, index+1) + newlist := make([]any, index+1) copy(newlist, list) list = newlist } @@ -332,7 +332,7 @@ func (t *parser) keyIndex() (int, error) { return strconv.Atoi(string(v)) } -func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interface{}, error) { +func (t *parser) listItem(list []any, i, nestedNameLevel int) ([]any, error) { if i < 0 { return list, fmt.Errorf("negative %d index not allowed", i) } @@ -356,7 +356,7 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa // Since Decode has its own buffer that consumes more characters (from underlying t.sc) than the ones actually decoded, // we invoke Decode on a separate reader built with a copy of what is left in t.sc. After Decode is executed, we // discard in t.sc the chars of the decoded json value (the number of those characters is returned by InputOffset). - var jsonval interface{} + var jsonval any dec := json.NewDecoder(strings.NewReader(t.sc.String())) if err = dec.Decode(&jsonval); err != nil { return list, err @@ -396,12 +396,12 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa if err != nil { return list, errors.Wrap(err, "error parsing index") } - var crtList []interface{} + var crtList []any if len(list) > i { // If nested list already exists, take the value of list to next cycle. existed := list[i] if existed != nil { - crtList = list[i].([]interface{}) + crtList = list[i].([]any) } } // Now we need to get the value after the ]. @@ -412,14 +412,14 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa return setIndex(list, i, list2) case last == '.': // We have a nested object. Send to t.key - inner := map[string]interface{}{} + inner := map[string]any{} if len(list) > i { var ok bool - inner, ok = list[i].(map[string]interface{}) + inner, ok = list[i].(map[string]any) if !ok { // We have indices out of order. Initialize empty value. - list[i] = map[string]interface{}{} - inner = list[i].(map[string]interface{}) + list[i] = map[string]any{} + inner = list[i].(map[string]any) } } @@ -462,18 +462,18 @@ func (t *parser) val() ([]rune, error) { return v, err } -func (t *parser) valList() ([]interface{}, error) { +func (t *parser) valList() ([]any, error) { r, _, e := t.sc.ReadRune() if e != nil { - return []interface{}{}, e + return []any{}, e } if r != '{' { t.sc.UnreadRune() - return []interface{}{}, ErrNotList + return []any{}, ErrNotList } - list := []interface{}{} + list := []any{} stop := runeSet([]rune{',', '}'}) for { switch rs, last, err := runesUntil(t.sc, stop); { @@ -525,7 +525,7 @@ func inMap(k rune, m map[rune]bool) bool { return ok } -func typedVal(v []rune, st bool) interface{} { +func typedVal(v []rune, st bool) any { val := string(v) if st { diff --git a/pkg/strvals/parser_test.go b/pkg/strvals/parser_test.go index 925aa97c6..f0746e922 100644 --- a/pkg/strvals/parser_test.go +++ b/pkg/strvals/parser_test.go @@ -25,48 +25,48 @@ import ( func TestSetIndex(t *testing.T) { tests := []struct { name string - initial []interface{} - expect []interface{} + initial []any + expect []any add int val int err bool }{ { name: "short", - initial: []interface{}{0, 1}, - expect: []interface{}{0, 1, 2}, + initial: []any{0, 1}, + expect: []any{0, 1, 2}, add: 2, val: 2, err: false, }, { name: "equal", - initial: []interface{}{0, 1}, - expect: []interface{}{0, 2}, + initial: []any{0, 1}, + expect: []any{0, 2}, add: 1, val: 2, err: false, }, { name: "long", - initial: []interface{}{0, 1, 2, 3, 4, 5}, - expect: []interface{}{0, 1, 2, 4, 4, 5}, + initial: []any{0, 1, 2, 3, 4, 5}, + expect: []any{0, 1, 2, 4, 4, 5}, add: 3, val: 4, err: false, }, { name: "negative", - initial: []interface{}{0, 1, 2, 3, 4, 5}, - expect: []interface{}{0, 1, 2, 3, 4, 5}, + initial: []any{0, 1, 2, 3, 4, 5}, + expect: []any{0, 1, 2, 3, 4, 5}, add: -1, val: 4, err: true, }, { name: "large", - initial: []interface{}{0, 1, 2, 3, 4, 5}, - expect: []interface{}{0, 1, 2, 3, 4, 5}, + initial: []any{0, 1, 2, 3, 4, 5}, + expect: []any{0, 1, 2, 3, 4, 5}, add: MaxIndex + 1, val: 4, err: true, @@ -103,53 +103,53 @@ func TestSetIndex(t *testing.T) { func TestParseSet(t *testing.T) { testsString := []struct { str string - expect map[string]interface{} + expect map[string]any err bool }{ { str: "long_int_string=1234567890", - expect: map[string]interface{}{"long_int_string": "1234567890"}, + expect: map[string]any{"long_int_string": "1234567890"}, err: false, }, { str: "boolean=true", - expect: map[string]interface{}{"boolean": "true"}, + expect: map[string]any{"boolean": "true"}, err: false, }, { str: "is_null=null", - expect: map[string]interface{}{"is_null": "null"}, + expect: map[string]any{"is_null": "null"}, err: false, }, { str: "zero=0", - expect: map[string]interface{}{"zero": "0"}, + expect: map[string]any{"zero": "0"}, err: false, }, } tests := []struct { str string - expect map[string]interface{} + expect map[string]any err bool }{ { "name1=null,f=false,t=true", - map[string]interface{}{"name1": nil, "f": false, "t": true}, + map[string]any{"name1": nil, "f": false, "t": true}, false, }, { "name1=value1", - map[string]interface{}{"name1": "value1"}, + map[string]any{"name1": "value1"}, false, }, { "name1=value1,name2=value2", - map[string]interface{}{"name1": "value1", "name2": "value2"}, + map[string]any{"name1": "value1", "name2": "value2"}, false, }, { "name1=value1,name2=value2,", - map[string]interface{}{"name1": "value1", "name2": "value2"}, + map[string]any{"name1": "value1", "name2": "value2"}, false, }, { @@ -158,27 +158,27 @@ func TestParseSet(t *testing.T) { }, { str: "name1=,name2=value2", - expect: map[string]interface{}{"name1": "", "name2": "value2"}, + expect: map[string]any{"name1": "", "name2": "value2"}, }, { str: "leading_zeros=00009", - expect: map[string]interface{}{"leading_zeros": "00009"}, + expect: map[string]any{"leading_zeros": "00009"}, }, { str: "zero_int=0", - expect: map[string]interface{}{"zero_int": 0}, + expect: map[string]any{"zero_int": 0}, }, { str: "long_int=1234567890", - expect: map[string]interface{}{"long_int": 1234567890}, + expect: map[string]any{"long_int": 1234567890}, }, { str: "boolean=true", - expect: map[string]interface{}{"boolean": true}, + expect: map[string]any{"boolean": true}, }, { str: "is_null=null", - expect: map[string]interface{}{"is_null": nil}, + expect: map[string]any{"is_null": nil}, err: false, }, { @@ -199,40 +199,40 @@ func TestParseSet(t *testing.T) { }, { "name1=one\\,two,name2=three\\,four", - map[string]interface{}{"name1": "one,two", "name2": "three,four"}, + map[string]any{"name1": "one,two", "name2": "three,four"}, false, }, { "name1=one\\=two,name2=three\\=four", - map[string]interface{}{"name1": "one=two", "name2": "three=four"}, + map[string]any{"name1": "one=two", "name2": "three=four"}, false, }, { "name1=one two three,name2=three two one", - map[string]interface{}{"name1": "one two three", "name2": "three two one"}, + map[string]any{"name1": "one two three", "name2": "three two one"}, false, }, { "outer.inner=value", - map[string]interface{}{"outer": map[string]interface{}{"inner": "value"}}, + map[string]any{"outer": map[string]any{"inner": "value"}}, false, }, { "outer.middle.inner=value", - map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}}, + map[string]any{"outer": map[string]any{"middle": map[string]any{"inner": "value"}}}, false, }, { "outer.inner1=value,outer.inner2=value2", - map[string]interface{}{"outer": map[string]interface{}{"inner1": "value", "inner2": "value2"}}, + map[string]any{"outer": map[string]any{"inner1": "value", "inner2": "value2"}}, false, }, { "outer.inner1=value,outer.middle.inner=value", - map[string]interface{}{ - "outer": map[string]interface{}{ + map[string]any{ + "outer": map[string]any{ "inner1": "value", - "middle": map[string]interface{}{ + "middle": map[string]any{ "inner": "value", }, }, @@ -249,7 +249,7 @@ func TestParseSet(t *testing.T) { }, { str: "name1.name2=", - expect: map[string]interface{}{"name1": map[string]interface{}{"name2": ""}}, + expect: map[string]any{"name1": map[string]any{"name2": ""}}, }, { str: "name1.=name2", @@ -261,12 +261,12 @@ func TestParseSet(t *testing.T) { }, { "name1={value1,value2}", - map[string]interface{}{"name1": []string{"value1", "value2"}}, + map[string]any{"name1": []string{"value1", "value2"}}, false, }, { "name1={value1,value2},name2={value1,value2}", - map[string]interface{}{ + map[string]any{ "name1": []string{"value1", "value2"}, "name2": []string{"value1", "value2"}, }, @@ -274,12 +274,12 @@ func TestParseSet(t *testing.T) { }, { "name1={1021,902}", - map[string]interface{}{"name1": []int{1021, 902}}, + map[string]any{"name1": []int{1021, 902}}, false, }, { "name1.name2={value1,value2}", - map[string]interface{}{"name1": map[string]interface{}{"name2": []string{"value1", "value2"}}}, + map[string]any{"name1": map[string]any{"name2": []string{"value1", "value2"}}}, false, }, { @@ -289,21 +289,21 @@ func TestParseSet(t *testing.T) { // List support { str: "list[0]=foo", - expect: map[string]interface{}{"list": []string{"foo"}}, + expect: map[string]any{"list": []string{"foo"}}, }, { str: "list[0].foo=bar", - expect: map[string]interface{}{ - "list": []interface{}{ - map[string]interface{}{"foo": "bar"}, + expect: map[string]any{ + "list": []any{ + map[string]any{"foo": "bar"}, }, }, }, { str: "list[0].foo=bar,list[0].hello=world", - expect: map[string]interface{}{ - "list": []interface{}{ - map[string]interface{}{"foo": "bar", "hello": "world"}, + expect: map[string]any{ + "list": []any{ + map[string]any{"foo": "bar", "hello": "world"}, }, }, }, @@ -313,15 +313,15 @@ func TestParseSet(t *testing.T) { }, { str: "list[0]=foo,list[1]=bar", - expect: map[string]interface{}{"list": []string{"foo", "bar"}}, + expect: map[string]any{"list": []string{"foo", "bar"}}, }, { str: "list[0]=foo,list[1]=bar,", - expect: map[string]interface{}{"list": []string{"foo", "bar"}}, + expect: map[string]any{"list": []string{"foo", "bar"}}, }, { str: "list[0]=foo,list[3]=bar", - expect: map[string]interface{}{"list": []interface{}{"foo", nil, nil, "bar"}}, + expect: map[string]any{"list": []any{"foo", nil, nil, "bar"}}, }, { str: "list[0]=foo,list[-20]=bar", @@ -333,41 +333,41 @@ func TestParseSet(t *testing.T) { }, { str: "noval[0]", - expect: map[string]interface{}{"noval": []interface{}{}}, + expect: map[string]any{"noval": []any{}}, }, { str: "noval[0]=", - expect: map[string]interface{}{"noval": []interface{}{""}}, + expect: map[string]any{"noval": []any{""}}, }, { str: "nested[0][0]=1", - expect: map[string]interface{}{"nested": []interface{}{[]interface{}{1}}}, + expect: map[string]any{"nested": []any{[]any{1}}}, }, { str: "nested[1][1]=1", - expect: map[string]interface{}{"nested": []interface{}{nil, []interface{}{nil, 1}}}, + expect: map[string]any{"nested": []any{nil, []any{nil, 1}}}, }, { str: "name1.name2[0].foo=bar,name1.name2[1].foo=bar", - expect: map[string]interface{}{ - "name1": map[string]interface{}{ - "name2": []map[string]interface{}{{"foo": "bar"}, {"foo": "bar"}}, + expect: map[string]any{ + "name1": map[string]any{ + "name2": []map[string]any{{"foo": "bar"}, {"foo": "bar"}}, }, }, }, { str: "name1.name2[1].foo=bar,name1.name2[0].foo=bar", - expect: map[string]interface{}{ - "name1": map[string]interface{}{ - "name2": []map[string]interface{}{{"foo": "bar"}, {"foo": "bar"}}, + expect: map[string]any{ + "name1": map[string]any{ + "name2": []map[string]any{{"foo": "bar"}, {"foo": "bar"}}, }, }, }, { str: "name1.name2[1].foo=bar", - expect: map[string]interface{}{ - "name1": map[string]interface{}{ - "name2": []map[string]interface{}{nil, {"foo": "bar"}}, + expect: map[string]any{ + "name1": map[string]any{ + "name2": []map[string]any{nil, {"foo": "bar"}}, }, }, }, @@ -433,20 +433,20 @@ func TestParseInto(t *testing.T) { tests := []struct { input string input2 string - got map[string]interface{} - expect map[string]interface{} + got map[string]any + expect map[string]any err bool }{ { input: "outer.inner1=value1,outer.inner3=value3,outer.inner4=4", - got: map[string]interface{}{ - "outer": map[string]interface{}{ + got: map[string]any{ + "outer": map[string]any{ "inner1": "overwrite", "inner2": "value2", }, }, - expect: map[string]interface{}{ - "outer": map[string]interface{}{ + expect: map[string]any{ + "outer": map[string]any{ "inner1": "value1", "inner2": "value2", "inner3": "value3", @@ -457,9 +457,9 @@ func TestParseInto(t *testing.T) { { input: "listOuter[0][0].type=listValue", input2: "listOuter[0][0].status=alive", - got: map[string]interface{}{}, - expect: map[string]interface{}{ - "listOuter": [][]interface{}{{map[string]string{ + got: map[string]any{}, + expect: map[string]any{ + "listOuter": [][]any{{map[string]string{ "type": "listValue", "status": "alive", }}}, @@ -469,9 +469,9 @@ func TestParseInto(t *testing.T) { { input: "listOuter[0][0].type=listValue", input2: "listOuter[1][0].status=alive", - got: map[string]interface{}{}, - expect: map[string]interface{}{ - "listOuter": [][]interface{}{ + got: map[string]any{}, + expect: map[string]any{ + "listOuter": [][]any{ { map[string]string{"type": "listValue"}, }, @@ -485,17 +485,17 @@ func TestParseInto(t *testing.T) { { input: "listOuter[0][1][0].type=listValue", input2: "listOuter[0][0][1].status=alive", - got: map[string]interface{}{ - "listOuter": []interface{}{ - []interface{}{ - []interface{}{ + got: map[string]any{ + "listOuter": []any{ + []any{ + []any{ map[string]string{"exited": "old"}, }, }, }, }, - expect: map[string]interface{}{ - "listOuter": [][][]interface{}{ + expect: map[string]any{ + "listOuter": [][][]any{ { { map[string]string{"exited": "old"}, @@ -543,15 +543,15 @@ func TestParseInto(t *testing.T) { } func TestParseIntoString(t *testing.T) { - got := map[string]interface{}{ - "outer": map[string]interface{}{ + got := map[string]any{ + "outer": map[string]any{ "inner1": "overwrite", "inner2": "value2", }, } input := "outer.inner1=1,outer.inner3=3" - expect := map[string]interface{}{ - "outer": map[string]interface{}{ + expect := map[string]any{ + "outer": map[string]any{ "inner1": "1", "inner2": "value2", "inner3": "3", @@ -579,20 +579,20 @@ func TestParseIntoString(t *testing.T) { func TestParseJSON(t *testing.T) { tests := []struct { input string - got map[string]interface{} - expect map[string]interface{} + got map[string]any + expect map[string]any err bool }{ { // set json scalars values, and replace one existing key input: "outer.inner1=\"1\",outer.inner3=3,outer.inner4=true,outer.inner5=\"true\"", - got: map[string]interface{}{ - "outer": map[string]interface{}{ + got: map[string]any{ + "outer": map[string]any{ "inner1": "overwrite", "inner2": "value2", }, }, - expect: map[string]interface{}{ - "outer": map[string]interface{}{ + expect: map[string]any{ + "outer": map[string]any{ "inner1": "1", "inner2": "value2", "inner3": 3, @@ -604,43 +604,43 @@ func TestParseJSON(t *testing.T) { }, { // set json objects and arrays, and replace one existing key input: "outer.inner1={\"a\":\"1\",\"b\":2,\"c\":[1,2,3]},outer.inner3=[\"new value 1\",\"new value 2\"],outer.inner4={\"aa\":\"1\",\"bb\":2,\"cc\":[1,2,3]},outer.inner5=[{\"A\":\"1\",\"B\":2,\"C\":[1,2,3]}]", - got: map[string]interface{}{ - "outer": map[string]interface{}{ - "inner1": map[string]interface{}{ + got: map[string]any{ + "outer": map[string]any{ + "inner1": map[string]any{ "x": "overwrite", }, "inner2": "value2", - "inner3": []interface{}{ + "inner3": []any{ "overwrite", }, }, }, - expect: map[string]interface{}{ - "outer": map[string]interface{}{ - "inner1": map[string]interface{}{"a": "1", "b": 2, "c": []interface{}{1, 2, 3}}, + expect: map[string]any{ + "outer": map[string]any{ + "inner1": map[string]any{"a": "1", "b": 2, "c": []any{1, 2, 3}}, "inner2": "value2", - "inner3": []interface{}{"new value 1", "new value 2"}, - "inner4": map[string]interface{}{"aa": "1", "bb": 2, "cc": []interface{}{1, 2, 3}}, - "inner5": []interface{}{map[string]interface{}{"A": "1", "B": 2, "C": []interface{}{1, 2, 3}}}, + "inner3": []any{"new value 1", "new value 2"}, + "inner4": map[string]any{"aa": "1", "bb": 2, "cc": []any{1, 2, 3}}, + "inner5": []any{map[string]any{"A": "1", "B": 2, "C": []any{1, 2, 3}}}, }, }, err: false, }, { // null assigment, and no value assigned (equivalent to null) input: "outer.inner1=,outer.inner3={\"aa\":\"1\",\"bb\":2,\"cc\":[1,2,3]},outer.inner3.cc[1]=null", - got: map[string]interface{}{ - "outer": map[string]interface{}{ - "inner1": map[string]interface{}{ + got: map[string]any{ + "outer": map[string]any{ + "inner1": map[string]any{ "x": "overwrite", }, "inner2": "value2", }, }, - expect: map[string]interface{}{ - "outer": map[string]interface{}{ + expect: map[string]any{ + "outer": map[string]any{ "inner1": nil, "inner2": "value2", - "inner3": map[string]interface{}{"aa": "1", "bb": 2, "cc": []interface{}{1, nil, 3}}, + "inner3": map[string]any{"aa": "1", "bb": 2, "cc": []any{1, nil, 3}}, }, }, err: false, @@ -679,10 +679,10 @@ func TestParseJSON(t *testing.T) { func TestParseFile(t *testing.T) { input := "name1=path1" - expect := map[string]interface{}{ + expect := map[string]any{ "name1": "value1", } - rs2v := func(rs []rune) (interface{}, error) { + rs2v := func(rs []rune) (any, error) { v := string(rs) if v != "path1" { t.Errorf("%s: runesToVal: Expected value path1, got %s", input, v) @@ -711,12 +711,12 @@ func TestParseFile(t *testing.T) { } func TestParseIntoFile(t *testing.T) { - got := map[string]interface{}{} + got := map[string]any{} input := "name1=path1" - expect := map[string]interface{}{ + expect := map[string]any{ "name1": "value1", } - rs2v := func(rs []rune) (interface{}, error) { + rs2v := func(rs []rune) (any, error) { v := string(rs) if v != "path1" { t.Errorf("%s: runesToVal: Expected value path1, got %s", input, v) @@ -767,13 +767,13 @@ func TestParseSetNestedLevels(t *testing.T) { } tests := []struct { str string - expect map[string]interface{} + expect map[string]any err bool errStr string }{ { "outer.middle.inner=value", - map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}}, + map[string]any{"outer": map[string]any{"middle": map[string]any{"inner": "value"}}}, false, "", },