From 4dfbaa40c6cd67e1df345889113a7879ec66136c Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Mon, 31 Aug 2026 12:58:34 -0700 Subject: [PATCH] Remove deprecated `internal/chart/v3/` code (#32365) Signed-off-by: George Jenkins --- internal/chart/v3/util/create.go | 11 +- internal/chart/v3/util/create_test.go | 10 +- internal/chart/v3/util/validate_name.go | 110 ------------------- internal/chart/v3/util/validate_name_test.go | 93 ---------------- pkg/cmd/create.go | 5 +- 5 files changed, 11 insertions(+), 218 deletions(-) delete mode 100644 internal/chart/v3/util/validate_name.go delete mode 100644 internal/chart/v3/util/validate_name_test.go diff --git a/internal/chart/v3/util/create.go b/internal/chart/v3/util/create.go index dcb5bbb39..0c143615e 100644 --- a/internal/chart/v3/util/create.go +++ b/internal/chart/v3/util/create.go @@ -18,7 +18,7 @@ package util import ( "fmt" - "io" + "log/slog" "os" "path/filepath" "regexp" @@ -642,12 +642,6 @@ spec: restartPolicy: Never ` -// Stderr is an io.Writer to which error messages can be written -// -// In Helm 4, this will be replaced. It is needed in Helm 3 to preserve API backward -// compatibility. -var Stderr io.Writer = os.Stderr - // CreateFrom creates a new chart, but scaffolds it from the src chart. func CreateFrom(chartfile *chart.Metadata, dest, src string) error { schart, err := loader.Load(src) @@ -795,8 +789,7 @@ func Create(name, dir string) (string, error) { for _, file := range files { if _, err := os.Stat(file.path); err == nil { - // There is no handle to a preferred output stream here. - fmt.Fprintf(Stderr, "WARNING: File %q already exists. Overwriting.\n", file.path) + slog.Warn("Overwriting existing file", slog.String("file", file.path)) } if err := writeFile(file.path, file.content); err != nil { return cdir, err diff --git a/internal/chart/v3/util/create_test.go b/internal/chart/v3/util/create_test.go index ddbbf6216..a227e4e7c 100644 --- a/internal/chart/v3/util/create_test.go +++ b/internal/chart/v3/util/create_test.go @@ -18,6 +18,7 @@ package util import ( "bytes" + "log/slog" "os" "path/filepath" "testing" @@ -98,7 +99,11 @@ func TestCreateFrom(t *testing.T) { func TestCreate_Overwrite(t *testing.T) { tdir := t.TempDir() - var errlog bytes.Buffer + prev := slog.Default() + t.Cleanup(func() { slog.SetDefault(prev) }) + + var logBuf bytes.Buffer + slog.SetDefault(slog.New(slog.NewJSONHandler(&logBuf, nil))) _, err := Create("foo", tdir) require.NoError(t, err) @@ -109,7 +114,6 @@ func TestCreate_Overwrite(t *testing.T) { writeFile(tplname, []byte("FOO")) // Now re-run the create - Stderr = &errlog _, err = Create("foo", tdir) require.NoError(t, err) @@ -118,7 +122,7 @@ func TestCreate_Overwrite(t *testing.T) { require.NotEqual(t, "FOO", string(data), "File that should have been modified was not.") - assert.NotEqual(t, 0, errlog.Len(), "Expected warnings about overwriting files.") + assert.NotEqual(t, 0, logBuf.Len(), "Expected warnings about overwriting files.") } func TestValidateChartName(t *testing.T) { diff --git a/internal/chart/v3/util/validate_name.go b/internal/chart/v3/util/validate_name.go deleted file mode 100644 index 7d85a5b88..000000000 --- a/internal/chart/v3/util/validate_name.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "errors" - "fmt" - "regexp" -) - -// validName is a regular expression for resource names. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -var validName = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`) - -var ( - // errMissingName indicates that a release (name) was not provided. - errMissingName = errors.New("no name provided") - - // errInvalidName indicates that an invalid release name was provided - errInvalidName = fmt.Errorf( - "invalid release name, must match regex %s and the length must not be longer than 53", - validName.String()) - - // errInvalidKubernetesName indicates that the name does not meet the Kubernetes - // restrictions on metadata names. - errInvalidKubernetesName = fmt.Errorf( - "invalid metadata name, must match regex %s and the length must not be longer than 253", - validName.String()) -) - -const ( - // According to the Kubernetes docs (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#rfc-1035-label-names) - // some resource names have a max length of 63 characters while others have a max - // length of 253 characters. As we cannot be sure the resources used in a chart, we - // therefore need to limit it to 63 chars and reserve 10 chars for additional part to name - // of the resource. The reason is that chart maintainers can use release name as part of - // the resource name (and some additional chars). - maxReleaseNameLen = 53 - // maxMetadataNameLen is the maximum length Kubernetes allows for any name. - maxMetadataNameLen = 253 -) - -// ValidateReleaseName performs checks for an entry for a Helm release name -// -// For Helm to allow a name, it must be below a certain character count (53) and also match -// a regular expression. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -func ValidateReleaseName(name string) error { - // This case is preserved for backwards compatibility - if name == "" { - return errMissingName - } - if len(name) > maxReleaseNameLen || !validName.MatchString(name) { - return errInvalidName - } - return nil -} - -// ValidateMetadataName validates the name field of a Kubernetes metadata object. -// -// Empty strings, strings longer than 253 chars, or strings that don't match the regexp -// will fail. -// -// According to the Kubernetes help text, the regular expression it uses is: -// -// [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)* -// -// This follows the above regular expression (but requires a full string match, not partial). -// -// The Kubernetes documentation is here, though it is not entirely correct: -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -// -// Deprecated: remove in Helm 4. Name validation now uses rules defined in -// pkg/lint/rules.validateMetadataNameFunc() -func ValidateMetadataName(name string) error { - if name == "" || len(name) > maxMetadataNameLen || !validName.MatchString(name) { - return errInvalidKubernetesName - } - return nil -} diff --git a/internal/chart/v3/util/validate_name_test.go b/internal/chart/v3/util/validate_name_test.go deleted file mode 100644 index 3ea768db2..000000000 --- a/internal/chart/v3/util/validate_name_test.go +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright The Helm Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestValidateReleaseName is a regression test for ValidateName -// -// Kubernetes has strict naming conventions for resource names. This test represents -// those conventions. -// -// See https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names -// -// NOTE: At the time of this writing, the docs above say that names cannot begin with -// digits. However, `kubectl`'s regular expression explicit allows this, and -// Kubernetes (at least as of 1.18) also accepts resources whose names begin with digits. -func TestValidateReleaseName(t *testing.T) { - names := map[string]bool{ - "": false, - "foo": true, - "foo.bar1234baz.seventyone": true, - "FOO": false, - "123baz": true, - "foo.BAR.baz": false, - "one-two": true, - "-two": false, - "one_two": false, - "a..b": false, - "%^&#$%*@^*@&#^": false, - "example:com": false, - "example%%com": false, - "a1111111111111111111111111111111111111111111111111111111111z": false, - } - for input, expectPass := range names { - err := ValidateReleaseName(input) - if expectPass { - assert.NoErrorf(t, err, "Expected release name %q to pass validation", input) - } else { - assert.Errorf(t, err, "Expected release name %q to fail validation, but it passed", input) - } - } -} - -func TestValidateMetadataName(t *testing.T) { - names := map[string]bool{ - "": false, - "foo": true, - "foo.bar1234baz.seventyone": true, - "FOO": false, - "123baz": true, - "foo.BAR.baz": false, - "one-two": true, - "-two": false, - "one_two": false, - "a..b": false, - "%^&#$%*@^*@&#^": false, - "example:com": false, - "example%%com": false, - "a1111111111111111111111111111111111111111111111111111111111z": true, - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z" + - "a1111111111111111111111111111111111111111111111111111111111z": false, - } - for input, expectPass := range names { - err := ValidateMetadataName(input) - if expectPass { - assert.NoError(t, err, "Expected %q to succeed", input) - } else { - assert.Error(t, err, "Expected %q to fail", input) - } - } -} diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index b38ce6a12..f7abb20dc 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -104,7 +104,7 @@ func (o *createOptions) run(out io.Writer) error { if !gates.ChartV3.IsEnabled() { return gates.ChartV3.Error() } - return o.createV3Chart(out) + return o.createV3Chart() default: return fmt.Errorf("unsupported chart API version: %s (supported: v2, v3)", o.chartAPIVersion) } @@ -136,7 +136,7 @@ func (o *createOptions) createV2Chart(out io.Writer) error { return err } -func (o *createOptions) createV3Chart(out io.Writer) error { +func (o *createOptions) createV3Chart() error { chartname := filepath.Base(o.name) cfile := &chartv3.Metadata{ Name: chartname, @@ -157,7 +157,6 @@ func (o *createOptions) createV3Chart(out io.Writer) error { return chartutilv3.CreateFrom(cfile, filepath.Dir(o.name), lstarter) } - chartutilv3.Stderr = out _, err := chartutilv3.Create(chartname, filepath.Dir(o.name)) return err }