Merge branch 'helm:main' into feature/rollback-revision-history

pull/31859/head
MrJack 2 weeks ago committed by GitHub
commit 1b360574a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -19,6 +19,7 @@ linters:
# Keep sorted alphabetically
enable:
- bidichk
- depguard
- dupl
- exhaustive
@ -38,6 +39,7 @@ linters:
- unused
- usestdlibvars
- usetesting
- whitespace
exclusions:
@ -101,8 +103,6 @@ linters:
- empty
- encoded-compare
- equal-values
- error-is-as
- error-nil
- expected-actual
- float-compare
- go-require

@ -33,9 +33,9 @@ require (
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/tetratelabs/wazero v1.11.0
github.com/tetratelabs/wazero v1.12.0
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/crypto v0.51.0
golang.org/x/crypto v0.52.0
golang.org/x/term v0.43.0
golang.org/x/text v0.37.0
gopkg.in/yaml.v3 v3.0.1 // indirect
@ -158,10 +158,10 @@ require (
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/net v0.55.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.44.0 // indirect
golang.org/x/sys v0.45.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.44.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect

@ -309,8 +309,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q=
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk=
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZopYU=
github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
@ -382,8 +382,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@ -400,8 +400,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -430,8 +430,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

@ -104,7 +104,7 @@ func TestMetadata(t *testing.T) {
is.Equal("foo.yaml", chrt.Name())
is.Equal("1.0.0", chrt.AppVersion())
is.Equal(nil, chrt.Validate())
is.NoError(chrt.Validate())
}
func TestIsRoot(t *testing.T) {

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

@ -242,7 +242,6 @@ data:
//
// See https://github.com/helm/helm/issues/7483
func TestStrictTemplateParsingMapError(t *testing.T) {
ch := chart.Chart{
Metadata: &chart.Metadata{
Name: "regression7483",
@ -371,7 +370,6 @@ func TestValidateTopIndentLevel(t *testing.T) {
t.Errorf("Expected %t for %q", shouldFail, doc)
}
}
}
// TestEmptyWithCommentsManifests checks the lint is not failing against empty manifests that contains only comments
@ -463,5 +461,4 @@ func TestIsYamlFileExtension(t *testing.T) {
t.Errorf("isYamlFileExtension(%s) = %v; want %v", test.filename, result, test.expected)
}
}
}

@ -337,7 +337,6 @@ icon: https://example.com/64x64.png
if text.String() != "" {
t.Errorf("Expected no message to Stderr, got %s", text.String())
}
}
// Packaging the chart on a Windows machine will produce an
@ -607,7 +606,6 @@ func verifyChart(t *testing.T, c *chart.Chart) {
t.Errorf("Expected %s version %s, got %s", dep.Name(), exp["version"], dep.Metadata.Version)
}
}
}
func verifyDependencies(t *testing.T, c *chart.Chart) {

@ -702,7 +702,6 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error {
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(name, dir string) (string, error) {
// Sanity-check the name of a chart so user doesn't create one that causes problems.
if err := validateChartName(name); err != nil {
return "", err

@ -459,7 +459,6 @@ func TestDependentChartAliases(t *testing.T) {
if aliasChart := getAliasDependency(c.Dependencies(), req[2]); aliasChart != nil {
t.Fatalf("expected no chart but got %s", aliasChart.Name())
}
}
func TestDependentChartWithSubChartsAbsentInDependency(t *testing.T) {

@ -79,7 +79,6 @@ 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

@ -24,7 +24,6 @@ import (
)
func TestColorizeStatus(t *testing.T) {
tests := []struct {
name string
status common.Status
@ -107,7 +106,6 @@ func TestColorizeStatus(t *testing.T) {
}
func TestColorizeHeader(t *testing.T) {
tests := []struct {
name string
header string
@ -149,7 +147,6 @@ func TestColorizeHeader(t *testing.T) {
}
func TestColorizeNamespace(t *testing.T) {
tests := []struct {
name string
namespace string

@ -33,7 +33,6 @@ type Client struct {
// New creates a new client
func New(u string) (*Client, error) {
// Validate we have a URL
if err := validate(u); err != nil {
return nil, err
@ -46,7 +45,6 @@ func New(u string) (*Client, error) {
// Validate if the base URL for monocular is valid.
func validate(u string) error {
// Check if it is parsable
p, err := url.Parse(u)
if err != nil {

@ -99,7 +99,6 @@ type ChartVersion struct {
// Search performs a search against the monocular search API
func (c *Client) Search(term string) ([]SearchResult, error) {
// Create the URL to the search endpoint
// Note, this is currently an internal API for the Hub. This should be
// formatted without showing how monocular operates.

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

@ -35,7 +35,6 @@ func TestPath(t *testing.T) {
}
for _, tt := range tests {
t.Setenv("HELM_PLUGINS", tt.helmPluginsDir)
baseIns := newBase(tt.source)
baseInsPath := baseIns.Path()

@ -90,7 +90,6 @@ func NewExtractor(source string) (Extractor, error) {
// - Beginning a path with a path separator is illegal
// - Rudimentary symlink protections are offered by SecureJoin.
func cleanJoin(root, dest string) (string, error) {
// On Windows, this is a drive separator. On UNIX-like, this is the path list separator.
// In neither case do we want to trust a TAR that contains these.
if strings.Contains(dest, ":") {

@ -124,7 +124,6 @@ func TestHTTPInstaller(t *testing.T) {
} else if err.Error() != "plugin already exists" {
t.Fatalf("expected error for plugin exists, got (%v)", err)
}
}
func TestHTTPInstallerNonExistentVersion(t *testing.T) {
@ -157,7 +156,6 @@ func TestHTTPInstallerNonExistentVersion(t *testing.T) {
if err := Install(i); err == nil {
t.Fatal("expected error from http client")
}
}
func TestHTTPInstallerUpdate(t *testing.T) {
@ -297,7 +295,6 @@ func TestExtract(t *testing.T) {
t.Fatalf("Expected %s to have %o mode but has %o (umask: %o)",
readmeFullPath, expectedReadmePerm, info.Mode().Perm(), currentUmask)
}
}
func TestCleanJoin(t *testing.T) {
@ -327,11 +324,9 @@ func TestCleanJoin(t *testing.T) {
t.Errorf("Test %d: Expected %q but got %q", i, fixture.expect, out)
}
}
}
func TestMediaTypeToExtension(t *testing.T) {
for mt, shouldPass := range map[string]bool{
"": false,
"application/gzip": true,

@ -72,7 +72,6 @@ type VerificationResult struct {
// InstallWithOptions installs a plugin with options.
func InstallWithOptions(i Installer, opts Options) (*VerificationResult, error) {
if err := os.MkdirAll(filepath.Dir(i.Path()), 0755); err != nil {
return nil, err
}

@ -185,5 +185,4 @@ func TestVCSInstallerUpdate(t *testing.T) {
} else if err.Error() != "plugin repo was modified" {
t.Fatalf("expected error for plugin modified, got (%v)", err)
}
}

@ -45,7 +45,6 @@ func peekAPIVersion(r io.Reader) (string, error) {
}
func loadMetadataLegacy(metadataData []byte) (*Metadata, error) {
var ml MetadataLegacy
d := yaml.NewDecoder(bytes.NewReader(metadataData))
// NOTE: No strict unmarshalling for legacy plugins - maintain backwards compatibility
@ -65,7 +64,6 @@ func loadMetadataLegacy(metadataData []byte) (*Metadata, error) {
}
func loadMetadataV1(metadataData []byte) (*Metadata, error) {
var mv1 MetadataV1
d := yaml.NewDecoder(bytes.NewReader(metadataData))
d.KnownFields(true)
@ -109,7 +107,6 @@ type prototypePluginManager struct {
}
func newPrototypePluginManager() (*prototypePluginManager, error) {
cc, err := wazero.NewCompilationCacheWithDir(helmpath.CachePath("wazero-build"))
if err != nil {
return nil, fmt.Errorf("failed to create wazero compilation cache: %w", err)
@ -229,7 +226,6 @@ func findPlugins(pluginsDirs []string, findFn findFunc, filterFn filterFunc) ([]
found = append(found, p)
}
}
}
return found, nil
@ -242,7 +238,6 @@ func makeDescriptorFilter(descriptor Descriptor) filterFunc {
// If name is specified, it must match
if descriptor.Name != "" && p.Metadata().Name != descriptor.Name {
return false
}
// If type is specified, it must match
if descriptor.Type != "" && p.Metadata().Type != descriptor.Type {

@ -62,7 +62,6 @@ name: "test-plugin"
}
func TestLoadDir(t *testing.T) {
makeMetadata := func(apiVersion string) Metadata {
usage := "hello [params]..."
if apiVersion == "legacy" {

@ -23,7 +23,6 @@ import (
)
func TestValidatePluginData(t *testing.T) {
// A mock plugin with no commands
mockNoCommand := mockSubprocessCLIPlugin(t, "foo")
mockNoCommand.metadata.RuntimeConfig = &RuntimeConfigSubprocess{

@ -28,7 +28,6 @@ func TestMakeOutputMessage(t *testing.T) {
ptm := pluginTypesIndex["getter/v1"]
outputType := reflect.Zero(ptm.outputType).Interface()
assert.IsType(t, schema.OutputMessageGetterV1{}, outputType)
}
func TestMakeConfig(t *testing.T) {

@ -99,7 +99,6 @@ type RuntimeExtismV1 struct {
var _ Runtime = (*RuntimeExtismV1)(nil)
func (r *RuntimeExtismV1) CreatePlugin(pluginDir string, metadata *Metadata) (Plugin, error) {
rc, ok := metadata.RuntimeConfig.(*RuntimeConfigExtismV1)
if !ok {
return nil, fmt.Errorf("invalid extism/v1 plugin runtime config type: %T", metadata.RuntimeConfig)
@ -139,7 +138,6 @@ func (p *ExtismV1PluginRuntime) Dir() string {
}
func (p *ExtismV1PluginRuntime) Invoke(ctx context.Context, input *Input) (*Output, error) {
var tmpDir string
if p.rc.FileSystem.CreateTempDir {
tmpDirInner, err := os.MkdirTemp(os.TempDir(), "helm-plugin-*")

@ -79,7 +79,7 @@ func TestRuntimeExtismV1InvokePlugin(t *testing.T) {
Name: "Phippy",
},
})
require.Nil(t, err)
require.NoError(t, err)
msg := output.Message.(schema.OutputMessageTestV1)
assert.Equal(t, "Hello, Phippy! (6)", msg.Greeting)

@ -48,7 +48,6 @@ func TestPrepareCommand(t *testing.T) {
}
func TestPrepareCommandExtraArgs(t *testing.T) {
cmdMain := "sh"
cmdArgs := []string{"-c", "echo \"test\""}
platformCommand := []PlatformCommand{

@ -26,7 +26,6 @@ import (
)
func TestSortManifests(t *testing.T) {
data := []struct {
name []string
path string
@ -183,7 +182,6 @@ metadata:
if !reflect.DeepEqual(expectedHooks, out.Events) {
t.Errorf("expected events: %v but got: %v", expectedHooks, out.Events)
}
}
}
if !found {

@ -54,7 +54,6 @@ func New(chartpath, cachepath string, registryClient *registry.Client) *Resolver
// Resolve resolves dependencies and returns a lock file with the resolution.
func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string) (*chart.Lock, error) {
// Now we clone the dependencies, locking as we go.
locked := make([]*chart.Dependency, len(reqs))
missing := []string{}
@ -146,7 +145,6 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string
Version: version,
},
}}
} else {
// Retrieve list of tags for repository
ref := fmt.Sprintf("%s/%s", strings.TrimPrefix(d.Repository, registry.OCIScheme+"://"), d.Name)

@ -238,7 +238,6 @@ func TestCopyDirFail_SrcIsNotDir(t *testing.T) {
if !errors.Is(err, errSrcNotDir) {
t.Fatalf("expected %v error for CopyDir(%s, %s), got %s", errSrcNotDir, srcdir, dstdir, err)
}
}
func TestCopyDirFail_DstExists(t *testing.T) {
@ -491,7 +490,6 @@ func setupInaccessibleDir(t *testing.T, op func(dir string) error) func() {
}
func TestIsDir(t *testing.T) {
var currentUID = os.Getuid()
if currentUID == 0 {
@ -544,7 +542,6 @@ func TestIsDir(t *testing.T) {
}
func TestIsSymlink(t *testing.T) {
var currentUID = os.Getuid()
if currentUID == 0 {

@ -77,7 +77,6 @@ func GetUserAgent() string {
// Get returns build info
func Get() BuildInfo {
makeKubeClientVersionString := func() string {
// Test builds don't include debug info / module info
// (And even if they did, we probably want a stable version during tests anyway)

@ -630,7 +630,6 @@ func GetVersionSet(client discovery.ServerResourcesInterface) (common.VersionSet
var ok bool
for _, r := range resources {
for _, rl := range r.APIResources {
// A Kind at a GroupVersion can show up more than once. We only want
// it displayed once in the final output.
id = path.Join(r.GroupVersion, rl.Kind)

@ -120,7 +120,6 @@ func (d *Dependency) dependencyStatus(chartpath string, dep *chart.Dependency, p
if r := statArchiveForStatus(archive, dep); r != "" {
return r
}
}
// End unnecessary code.

@ -119,7 +119,6 @@ func (m *Metadata) FormattedDepNames() string {
continue
}
depsNames = append(depsNames, ac.Name())
}
sort.StringSlice(depsNames).Sort()

@ -35,7 +35,6 @@ import (
func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent,
waitStrategy kube.WaitStrategy, waitOptions []kube.WaitOption,
timeout time.Duration, serverSideApply bool) error {
shutdown, err := cfg.execHookWithDelayedShutdown(rl, hook, waitStrategy, waitOptions, timeout, serverSideApply)
if shutdown == nil {
return err
@ -59,7 +58,6 @@ func shutdownNoOp() error {
func (cfg *Configuration) execHookWithDelayedShutdown(rl *release.Release, hook release.HookEvent,
waitStrategy kube.WaitStrategy, waitOptions []kube.WaitOption, timeout time.Duration,
serverSideApply bool) (ExecuteShutdownFunc, error) {
executingHooks := []*release.Hook{}
for _, h := range rl.Hooks {
@ -179,7 +177,6 @@ func (x hookByWeight) Less(i, j int) bool {
// deleteHookByPolicy deletes a hook if the hook policy instructs it to
func (cfg *Configuration) deleteHookByPolicy(h *release.Hook, policy release.HookDeletePolicy,
waitStrategy kube.WaitStrategy, waitOptions []kube.WaitOption, timeout time.Duration) error {
// Never delete CustomResourceDefinitions; this could cause lots of
// cascading garbage collection.
if h.Kind == "CustomResourceDefinition" {
@ -214,7 +211,6 @@ func (cfg *Configuration) deleteHookByPolicy(h *release.Hook, policy release.Hoo
// deleteHooksByPolicy deletes all hooks if the hook policy instructs it to
func (cfg *Configuration) deleteHooksByPolicy(hooks []*release.Hook, policy release.HookDeletePolicy,
waitStrategy kube.WaitStrategy, waitOptions []kube.WaitOption, timeout time.Duration) error {
for _, h := range hooks {
if err := cfg.deleteHookByPolicy(h, policy, waitStrategy, waitOptions, timeout); err != nil {
return err

@ -737,7 +737,6 @@ func TestInstallRelease_RollbackOnFailure(t *testing.T) {
})
}
func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "interrupted-release"
@ -767,7 +766,6 @@ func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
is.Equal(goroutines+1, instAction.getGoroutineCount()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, instAction.getGoroutineCount())
}
func TestNameTemplate(t *testing.T) {
testCases := []nameTemplateTestCase{
@ -804,7 +802,6 @@ func TestNameTemplate(t *testing.T) {
}
for _, tc := range testCases {
n, err := TemplateName(tc.tpl)
if err != nil {
if tc.expectedErrorStr == "" {
@ -867,7 +864,7 @@ func TestInstallReleaseOutputDir(t *testing.T) {
test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(dir, "hello/templates/empty"))
is.True(errors.Is(err, fs.ErrNotExist))
is.ErrorIs(err, fs.ErrNotExist)
}
func TestInstallOutputDirWithReleaseName(t *testing.T) {
@ -903,7 +900,7 @@ func TestInstallOutputDirWithReleaseName(t *testing.T) {
test.AssertGoldenFile(t, filepath.Join(newDir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(newDir, "hello/templates/empty"))
is.True(errors.Is(err, fs.ErrNotExist))
is.ErrorIs(err, fs.ErrNotExist)
}
func TestNameAndChart(t *testing.T) {
@ -1168,7 +1165,7 @@ func TestInstallCRDs_AlreadyExist(t *testing.T) {
mockChart := buildChart(withFile(mockFile))
crdsToInstall := mockChart.CRDObjects()
assert.Nil(t, instAction.installCRDs(crdsToInstall))
assert.NoError(t, instAction.installCRDs(crdsToInstall))
}
func TestInstallCRDs_KubeClient_BuildError(t *testing.T) {
@ -1227,7 +1224,7 @@ func TestCheckDependencies(t *testing.T) {
dependency := chart.Dependency{Name: "hello"}
mockChart := buildChart(withDependency())
assert.Nil(t, CheckDependencies(mockChart, []ci.Dependency{&dependency}))
assert.NoError(t, CheckDependencies(mockChart, []ci.Dependency{&dependency}))
}
func TestCheckDependencies_MissingDependency(t *testing.T) {

@ -150,7 +150,6 @@ func TestValidateVersion(t *testing.T) {
if !errors.Is(err, tt.wantErr) {
t.Errorf("Expected {%v}, got {%v}", tt.wantErr, err)
}
}
})
}

@ -37,7 +37,7 @@ func TestWithCertFile(t *testing.T) {
certFile := "testdata/cert.pem"
opt := WithCertFile(certFile)
assert.Nil(t, opt(client))
assert.NoError(t, opt(client))
assert.Equal(t, certFile, client.certFile)
}
@ -47,7 +47,7 @@ func TestWithInsecure(t *testing.T) {
opt := WithInsecure(true)
assert.Nil(t, opt(client))
assert.NoError(t, opt(client))
assert.True(t, client.insecure)
}
@ -58,7 +58,7 @@ func TestWithKeyFile(t *testing.T) {
keyFile := "testdata/key.pem"
opt := WithKeyFile(keyFile)
assert.Nil(t, opt(client))
assert.NoError(t, opt(client))
assert.Equal(t, keyFile, client.keyFile)
}
@ -69,7 +69,7 @@ func TestWithCAFile(t *testing.T) {
caFile := "testdata/ca.pem"
opt := WithCAFile(caFile)
assert.Nil(t, opt(client))
assert.NoError(t, opt(client))
assert.Equal(t, caFile, client.caFile)
}
@ -79,6 +79,6 @@ func TestWithPlainHTTPLogin(t *testing.T) {
opt := WithPlainHTTPLogin(true)
assert.Nil(t, opt(client))
assert.NoError(t, opt(client))
assert.True(t, client.plainHTTP)
}

@ -40,7 +40,6 @@ func filterManifestsToKeep(manifests []releaseutil.Manifest) (keep, remaining []
if resourcePolicyType == kube.KeepPolicy {
keep = append(keep, m)
}
}
return keep, remaining
}

@ -268,7 +268,6 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chartv2.Chart, vals map[str
return nil, nil, false, err
}
}
}
// determine if values will be reused

@ -446,7 +446,6 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
}
func TestUpgradeRelease_Interrupted_RollbackOnFailure(t *testing.T) {
is := assert.New(t)
req := require.New(t)
@ -716,7 +715,7 @@ func TestGetUpgradeServerSideValue(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
serverSideApply, err := getUpgradeServerSideValue(tt.actionServerSideOption, tt.releaseApplyMethod)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, tt.expectedServerSideApply, serverSideApply)
})
}
@ -741,7 +740,6 @@ func TestGetUpgradeServerSideValue(t *testing.T) {
assert.ErrorContains(t, err, tt.expectedErrorMsg)
})
}
}
func TestUpgradeRun_UnreachableKubeClient(t *testing.T) {

@ -273,7 +273,6 @@ func TestValidateNameAndGenerateName(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
skip, err := validateNameAndGenerateName(tc.info)
if tc.wantErr {

@ -167,7 +167,6 @@ func makeDefaultCapabilities() (*Capabilities, error) {
}
func newCapabilities(kubeVersionMajor, kubeVersionMinor uint64) (*Capabilities, error) {
version := fmt.Sprintf("v%d.%d.0", kubeVersionMajor, kubeVersionMinor)
return &Capabilities{
KubeVersion: KubeVersion{

@ -666,7 +666,6 @@ func TestMergeTables(t *testing.T) {
}
func TestCoalesceValuesWarnings(t *testing.T) {
c := withDeps(&chart.Chart{
Metadata: &chart.Metadata{Name: "level1"},
Values: map[string]any{
@ -724,7 +723,6 @@ func TestCoalesceValuesWarnings(t *testing.T) {
assert.Contains(t, warnings, "warning: skipped value for level1.level2.level3.boat: Not a table.")
assert.Contains(t, warnings, "warning: destination for level1.level2.level3.spear.tip is a table. Ignoring non-table value (true)")
assert.Contains(t, warnings, "warning: cannot overwrite table with non table for level1.level2.level3.spear.sail (map[cotton:true])")
}
func TestConcatPrefix(t *testing.T) {

@ -25,7 +25,6 @@ import (
)
func TestToRenderValues(t *testing.T) {
chartValues := map[string]any{
"name": "al Rashid",
"where": map[string]any{

@ -100,7 +100,6 @@ func LoadDir(dir string) (chart.Charter, error) {
default:
return nil, errors.New("unsupported chart version")
}
}
// FileLoader loads a chart from a file

@ -104,7 +104,7 @@ func TestMetadata(t *testing.T) {
is.Equal("foo.yaml", chrt.Name())
is.Equal("1.0.0", chrt.AppVersion())
is.Equal(nil, chrt.Validate())
is.NoError(chrt.Validate())
}
func TestIsRoot(t *testing.T) {

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

@ -62,7 +62,6 @@ func TemplateLinterSkipSchemaValidation(skipSchemaValidation bool) TemplateLinte
}
func newTemplateLinter(linter *support.Linter, namespace string, values map[string]any, options ...TemplateLinterOption) templateLinter {
result := templateLinter{
linter: linter,
values: values,

@ -257,7 +257,6 @@ data:
//
// See https://github.com/helm/helm/issues/7483
func TestStrictTemplateParsingMapError(t *testing.T) {
ch := chart.Chart{
Metadata: &chart.Metadata{
Name: "regression7483",
@ -390,7 +389,6 @@ func TestValidateTopIndentLevel(t *testing.T) {
t.Errorf("Expected %t for %q", shouldFail, doc)
}
}
}
// TestEmptyWithCommentsManifests checks the lint is not failing against empty manifests that contains only comments
@ -486,5 +484,4 @@ func TestIsYamlFileExtension(t *testing.T) {
t.Errorf("isYamlFileExtension(%s) = %v; want %v", test.filename, result, test.expected)
}
}
}

@ -390,7 +390,6 @@ icon: https://example.com/64x64.png
if text.String() != "" {
t.Errorf("Expected no message to Stderr, got %s", text.String())
}
}
// Packaging the chart on a Windows machine will produce an
@ -660,7 +659,6 @@ func verifyChart(t *testing.T, c *chart.Chart) {
t.Errorf("Expected %s version %s, got %s", dep.Name(), exp["version"], dep.Metadata.Version)
}
}
}
func verifyDependencies(t *testing.T, c *chart.Chart) {

@ -701,7 +701,6 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error {
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func Create(name, dir string) (string, error) {
// Sanity-check the name of a chart so user doesn't create one that causes problems.
if err := validateChartName(name); err != nil {
return "", err

@ -459,7 +459,6 @@ func TestDependentChartAliases(t *testing.T) {
if aliasChart := getAliasDependency(c.Dependencies(), req[2]); aliasChart != nil {
t.Fatalf("expected no chart but got %s", aliasChart.Name())
}
}
func TestDependentChartWithSubChartsAbsentInDependency(t *testing.T) {

@ -79,7 +79,6 @@ 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

@ -51,7 +51,6 @@ func checkFileCompletion(t *testing.T, cmdName string, shouldBePerformed bool) {
if shouldBePerformed {
t.Errorf("Unexpected directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName)
} else {
t.Errorf("Did not receive directive ShellCompDirectiveNoFileComp when completing '%s'", cmdName)
}
t.Log(out)

@ -220,7 +220,6 @@ func (p *postRendererArgsSlice) Type() string {
}
func (p *postRendererArgsSlice) Set(val string) error {
// a post-renderer defined by a user may accept empty arguments
p.options.args = append(p.options.args, val)

@ -77,7 +77,6 @@ func newGetMetadataCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
}
func (w metadataWriter) WriteTable(out io.Writer) error {
formatApplyMethod := func(applyMethod string) string {
switch applyMethod {
case "":

@ -43,7 +43,6 @@ func addDryRunFlag(cmd *cobra.Command) {
// Determine the `action.DryRunStrategy` given -dry-run=<value>` flag (or absence of)
// Legacy usage of the flag: boolean values, and `--dry-run` (without value) are supported, and log warnings emitted
func cmdGetDryRunFlagStrategy(cmd *cobra.Command, isTemplate bool) (action.DryRunStrategy, error) {
f := cmd.Flag("dry-run")
v := f.Value.String()

@ -157,7 +157,6 @@ func resetEnv() func() {
}
func TestCmdGetDryRunFlagStrategy(t *testing.T) {
type testCaseExpectedLog struct {
Level string
Msg string
@ -274,7 +273,6 @@ func TestCmdGetDryRunFlagStrategy(t *testing.T) {
}
for name, tc := range testCases {
logBuf := new(bytes.Buffer)
logger := slog.New(slog.NewJSONHandler(logBuf, nil))
slog.SetDefault(logger)
@ -290,14 +288,14 @@ func TestCmdGetDryRunFlagStrategy(t *testing.T) {
if tc.ExpectedError {
assert.Error(t, err)
} else {
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, tc.ExpectedStrategy, dryRunStrategy)
}
if tc.ExpectedLog != nil {
logResult := map[string]string{}
err = json.Unmarshal(logBuf.Bytes(), &logResult)
require.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, tc.ExpectedLog.Level, logResult["level"])
assert.Equal(t, tc.ExpectedLog.Msg, logResult["msg"])

@ -268,7 +268,6 @@ func getReleaseHistory(rls []*release.Release) (history releaseHistory) {
}
if !r.Info.LastDeployed.IsZero() {
rInfo.Updated = r.Info.LastDeployed
}
history = append(history, rInfo)
}

@ -60,7 +60,6 @@ func TestLintCmdWithQuietFlag(t *testing.T) {
wantError: true,
}}
runTestCmd(t, tests)
}
func TestLintCmdWithKubeVersionFlag(t *testing.T) {

@ -333,7 +333,6 @@ func loadFile(path string) (*pluginCommand, error) {
// to obtain the dynamic completion choices. It must pass all the flags and sub-commands
// specified in the command-line to the plugin.complete executable (except helm's global flags)
func pluginDynamicComp(plug plugin.Plugin, cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
subprocessPlug, ok := plug.(*plugin.SubprocessPluginRuntime)
if !ok {
// Completion only supported for subprocess plugins (TODO: fix this)

@ -260,7 +260,6 @@ func TestPullCmd(t *testing.T) {
if out != outString {
t.Errorf("%q: expected verification output %q, got %q", tt.name, outString, out)
}
}
ef := filepath.Join(outdir, tt.expectFile)

@ -28,7 +28,6 @@ import (
)
func TestRepoIndexCmd(t *testing.T) {
dir := t.TempDir()
comp := filepath.Join(dir, "compressedchart-0.1.0.tgz")

@ -103,7 +103,6 @@ func TestRepoRemove(t *testing.T) {
cacheIndex, cacheChart := createCacheFiles(rootDir, repoName)
cacheFiles[repoName] = []string{cacheIndex, cacheChart}
}
// Create repo remove command

@ -355,7 +355,6 @@ func hookOutputWriter(_, _, _ string) io.Writer {
}
func checkForExpiredRepos(repofile string) {
expiredRepos := []struct {
name string
old string
@ -399,7 +398,6 @@ func checkForExpiredRepos(repofile string) {
)
}
}
}
func newRegistryClient(

@ -29,7 +29,6 @@ Use search subcommands to search different locations for charts.
`
func newSearchCmd(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "search [keyword]",
Short: "search for a keyword in charts",

@ -123,7 +123,6 @@ func (i *Index) Search(term string, threshold int, regexp bool) ([]*Result, erro
// calcScore calculates a score for a match.
func (i *Index) calcScore(index int, matchline string) int {
// This is currently tied to the fact that sep is a single char.
splits := []int{}
s := rune(sep[0])

@ -149,7 +149,6 @@ func TestAddRepo_Sort(t *testing.T) {
}
func TestSearchByName(t *testing.T) {
tests := []struct {
name string
query string
@ -245,7 +244,6 @@ func TestSearchByName(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
charts, err := i.Search(tt.query, 100, tt.regexp)
if err != nil {
if tt.fail {
@ -274,7 +272,6 @@ func TestSearchByName(t *testing.T) {
t.Errorf("[%d]: Expected name %q, got %q", i, ex.Name, got.Name)
}
}
})
}
}

@ -196,5 +196,4 @@ func (h *hubSearchWriter) encodeByFormat(out io.Writer, format output.Format) er
// WriteJSON and WriteYAML, we shouldn't get invalid types
return nil
}
}

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

@ -142,7 +142,6 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return err
}
}
}
}

@ -59,7 +59,6 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return validationErr
}
for i := range args {
res, err := client.Run(args[i])
if err != nil {
return err

@ -34,7 +34,6 @@ import (
)
func TestUpgradeCmd(t *testing.T) {
tmpChart := t.TempDir()
cfile := &chart.Chart{
Metadata: &chart.Metadata{
@ -222,7 +221,6 @@ func TestUpgradeWithValue(t *testing.T) {
if !strings.Contains(updatedRel.Manifest, "drink: tea") {
t.Errorf("The value is not set correctly. manifest: %s", updatedRel.Manifest)
}
}
func TestUpgradeWithStringValue(t *testing.T) {
@ -253,11 +251,9 @@ func TestUpgradeWithStringValue(t *testing.T) {
if !strings.Contains(updatedRel.Manifest, "drink: coffee") {
t.Errorf("The value is not set correctly. manifest: %s", updatedRel.Manifest)
}
}
func TestUpgradeInstallWithSubchartNotes(t *testing.T) {
releaseName := "wacky-bunny-v1"
relMock, ch, _ := prepareMockRelease(t, releaseName)
@ -289,11 +285,9 @@ func TestUpgradeInstallWithSubchartNotes(t *testing.T) {
if !strings.Contains(upgradedRel.Info.Notes, "SUBCHART NOTES") {
t.Errorf("The subchart notes are not set correctly. NOTES: %s", upgradedRel.Info.Notes)
}
}
func TestUpgradeWithValuesFile(t *testing.T) {
releaseName := "funny-bunny-v4"
relMock, ch, chartPath := prepareMockRelease(t, releaseName)
@ -321,11 +315,9 @@ func TestUpgradeWithValuesFile(t *testing.T) {
if !strings.Contains(updatedRel.Manifest, "drink: beer") {
t.Errorf("The value is not set correctly. manifest: %s", updatedRel.Manifest)
}
}
func TestUpgradeWithValuesFromStdin(t *testing.T) {
releaseName := "funny-bunny-v5"
relMock, ch, chartPath := prepareMockRelease(t, releaseName)
@ -361,7 +353,6 @@ func TestUpgradeWithValuesFromStdin(t *testing.T) {
}
func TestUpgradeInstallWithValuesFromStdin(t *testing.T) {
releaseName := "funny-bunny-v6"
_, _, chartPath := prepareMockRelease(t, releaseName)
@ -392,7 +383,6 @@ func TestUpgradeInstallWithValuesFromStdin(t *testing.T) {
if !strings.Contains(updatedRel.Manifest, "drink: beer") {
t.Errorf("The value is not set correctly. manifest: %s", updatedRel.Manifest)
}
}
func prepareMockRelease(t *testing.T, releaseName string) (func(n string, v int, ch *chart.Chart) *release.Release, *chart.Chart, string) {

@ -22,7 +22,6 @@ import (
)
func TestVerifyCmd(t *testing.T) {
statExe := "stat"
statPathMsg := "no such file or directory"
statFileMsg := statPathMsg

@ -282,7 +282,6 @@ func (c *ChartDownloader) DownloadToCache(ref, version string) (string, *provena
// If provenance is requested, verify it.
ver := &provenance.Verification{}
if c.Verify > VerifyNever {
ppth, err := c.Cache.Get(digest32, CacheProv)
if err == nil {
slog.Debug("found provenance in cache", "id", digestString)
@ -308,7 +307,6 @@ func (c *ChartDownloader) DownloadToCache(ref, version string) (string, *provena
}
if c.Verify != VerifyLater {
// provenance files pin to a specific name so this needs to be accounted for
// when verifying.
// Note, this does make an assumption that the name/version is unique to a

@ -502,11 +502,9 @@ Loop:
// in a known repo and attempt to ensure the data is present for steps like
// version resolution.
func (m *Manager) ensureMissingRepos(repoNames map[string]string, deps []*chart.Dependency) (map[string]string, error) {
var ru []*repo.Entry
for _, dd := range deps {
// If the chart is in the local charts directory no repository needs
// to be specified.
if dd.Repository == "" {
@ -679,7 +677,6 @@ func dedupeRepos(repos []*repo.Entry) []*repo.Entry {
}
func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error {
var wg sync.WaitGroup
localRepos := dedupeRepos(repos)

@ -27,6 +27,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
@ -657,7 +658,6 @@ func TestRenderDependency(t *testing.T) {
if out["outerchart/templates/outer"] != expect {
t.Errorf("Expected %q, got %q", expect, out["outer"])
}
}
func TestRenderNestedValues(t *testing.T) {
@ -813,7 +813,6 @@ func TestRenderBuiltinValues(t *testing.T) {
t.Errorf("Expected %q, got %q", expect, out[file])
}
}
}
func TestAlterFuncMap_include(t *testing.T) {
@ -1009,7 +1008,6 @@ func TestAlterFuncMap_tplinclude(t *testing.T) {
if got := out["TplFunction/templates/base"]; got != expect {
t.Errorf("Expected %q, got %q (%v)", expect, got, out)
}
}
func TestRenderRecursionLimit(t *testing.T) {
@ -1068,7 +1066,6 @@ func TestRenderRecursionLimit(t *testing.T) {
if got := out["overlook/templates/quote"]; got != expect {
t.Errorf("Expected %q, got %q (%v)", expect, got, out)
}
}
func TestRenderLoadTemplateForTplFromFile(t *testing.T) {
@ -1319,7 +1316,6 @@ func TestRenderTplMissingKeyString(t *testing.T) {
if !strings.Contains(errTxt, "noSuchKey") {
t.Errorf("Expected error to contain 'noSuchKey', got %s", errTxt)
}
}
func TestNestedHelpersProducesMultilineStacktrace(t *testing.T) {
@ -1357,7 +1353,7 @@ NestedHelperFunctions/charts/common/templates/_helpers_2.tpl:1:49
}
_, err := Render(c, vals)
assert.NotNil(t, err)
require.Error(t, err)
assert.Equal(t, expectedErrorMessage, err.Error())
}
@ -1391,7 +1387,7 @@ template: no template "nested_helper.name" associated with template "gotpl"`
}
_, err := Render(c, vals)
assert.NotNil(t, err)
require.Error(t, err)
assert.Equal(t, expectedErrorMessage, err.Error())
}

@ -510,7 +510,6 @@ func TestDownloadInsecureSkipTLSVerify(t *testing.T) {
if _, err = g.Get(u.String()); err != nil {
t.Error(err)
}
}
func TestHTTPGetterTarDownload(t *testing.T) {

@ -41,7 +41,6 @@ func collectGetterPlugins(settings *cli.EnvSettings) (Providers, error) {
env := plugin.FormatEnv(settings.EnvVars())
pluginConstructorBuilder := func(plg plugin.Plugin) Constructor {
return func(option ...Option) (Getter, error) {
return &getterPlugin{
options: append([]Option{}, option...),
plg: plg,

@ -38,7 +38,6 @@ const (
type lazypath string
func (l lazypath) path(helmEnvVar, xdgEnvVar string, defaultFn func() string, elem ...string) string {
// There is an order to checking for a path.
// 1. See if a Helm specific environment variable has been set.
// 2. Check if an XDG environment variable is set

@ -521,7 +521,6 @@ func determineFieldValidationDirective(validate bool) FieldValidationDirective {
}
func buildResourceList(f Factory, namespace string, validationDirective FieldValidationDirective, reader io.Reader, transformRequest resource.RequestTransform) (ResourceList, error) {
schema, err := f.Validator(string(validationDirective))
if err != nil {
return nil, err
@ -859,7 +858,6 @@ func (c *Client) Update(originals, targets ResourceList, options ...ClientUpdate
slog.String("fieldValidationDirective", string(updateOptions.fieldValidationDirective)),
slog.Bool("upgradeClientSideFieldManager", updateOptions.upgradeClientSideFieldManager))
return func(original, target *resource.Info) error {
logger := c.Logger().With(
slog.String("namespace", target.Namespace),
slog.String("name", target.Name),
@ -954,7 +952,6 @@ func isIncompatibleServerError(err error) bool {
// getManagedFieldsManager returns the manager string. If one was set it will be returned.
// Otherwise, one is calculated based on the name of the binary.
func getManagedFieldsManager() string {
// When a manager is explicitly set use it
if ManagedFieldsManager != "" {
return ManagedFieldsManager
@ -1102,7 +1099,6 @@ func createPatch(original runtime.Object, target *resource.Info, threeWayMergeFo
}
func replaceResource(target *resource.Info, fieldValidationDirective FieldValidationDirective) error {
helper := resource.NewHelper(target.Client, target.Mapping).
WithFieldValidation(string(fieldValidationDirective)).
WithFieldManager(getManagedFieldsManager())
@ -1117,11 +1113,9 @@ func replaceResource(target *resource.Info, fieldValidationDirective FieldValida
}
return nil
}
func patchResourceClientSide(original runtime.Object, target *resource.Info, threeWayMergeForUnstructured bool) error {
patch, patchType, err := createPatch(original, target, threeWayMergeForUnstructured)
if err != nil {
return fmt.Errorf("failed to create patch: %w", err)
@ -1155,14 +1149,12 @@ func patchResourceClientSide(original runtime.Object, target *resource.Info, thr
// that upgrade CSA managed fields to SSA apply
// see: https://github.com/kubernetes/kubernetes/pull/112905
func upgradeClientSideFieldManager(info *resource.Info, dryRun bool, fieldValidationDirective FieldValidationDirective) (bool, error) {
fieldManagerName := getManagedFieldsManager()
patched := false
err := retry.RetryOnConflict(
retry.DefaultRetry,
func() error {
if err := info.Get(); err != nil {
return fmt.Errorf("failed to get object %s/%s %s: %w", info.Namespace, info.Name, info.Mapping.GroupVersionKind.String(), err)
}

@ -282,7 +282,6 @@ func TestCreate(t *testing.T) {
c := newTestClient(t)
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
client := NewRequestResponseLogClient(t, func(previous []RequestResponseAction, req *http.Request) (*http.Response, error) {
return tc.Callback(t, tc, previous, req)
})
@ -317,7 +316,6 @@ func TestCreate(t *testing.T) {
}
assert.Equal(t, tc.ExpectedActions, actions)
})
}
}
@ -444,7 +442,6 @@ func TestUpdate(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
listOriginal := tc.OriginalPods
listTarget := tc.TargetPods
@ -1410,7 +1407,6 @@ func TestIsReachable(t *testing.T) {
if !strings.Contains(err.Error(), tt.errorContains) {
t.Errorf("expected error message to contain '%s', got: %v", tt.errorContains, err)
}
} else {
if err != nil {
t.Errorf("expected no error but got: %v", err)
@ -1488,7 +1484,6 @@ func TestReplaceResource(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
testFactory := cmdtesting.NewTestFactory()
t.Cleanup(testFactory.Cleanup)
@ -1611,7 +1606,6 @@ func TestPatchResourceClientSide(t *testing.T) {
t.Fail()
return nil, nil
},
ExpectedErrorContains: "cannot patch \"whale\" with kind Pod: the server reported a conflict",
},
@ -1633,14 +1627,12 @@ func TestPatchResourceClientSide(t *testing.T) {
t.Fail()
return nil, nil // newResponse(http.StatusOK, &tc.TargetPods.Items[0])
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
testFactory := cmdtesting.NewTestFactory()
t.Cleanup(testFactory.Cleanup)
@ -1824,7 +1816,6 @@ func TestPatchResourceServerSide(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
testFactory := cmdtesting.NewTestFactory()
t.Cleanup(testFactory.Cleanup)
@ -1855,7 +1846,6 @@ func TestPatchResourceServerSide(t *testing.T) {
}
func TestDetermineFieldValidationDirective(t *testing.T) {
assert.Equal(t, FieldValidationDirectiveIgnore, determineFieldValidationDirective(false))
assert.Equal(t, FieldValidationDirectiveStrict, determineFieldValidationDirective(true))
}

@ -68,6 +68,12 @@ func alwaysReady(_ *unstructured.Unstructured) (*status.Result, error) {
}, nil
}
func getStatusWatcher(dynamicClient dynamic.Interface, mapper meta.RESTMapper) *watcher.DefaultStatusWatcher {
sw := watcher.NewDefaultStatusWatcher(dynamicClient, mapper)
sw.ResyncPeriod = 3 * time.Minute
return sw
}
func (w *statusWaiter) WatchUntilReady(resourceList ResourceList, timeout time.Duration) error {
if timeout == 0 {
timeout = DefaultStatusWatcherTimeout
@ -75,7 +81,7 @@ func (w *statusWaiter) WatchUntilReady(resourceList ResourceList, timeout time.D
ctx, cancel := w.contextWithTimeout(w.watchUntilReadyCtx, timeout)
defer cancel()
w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout)
sw := watcher.NewDefaultStatusWatcher(w.client, w.restMapper)
sw := getStatusWatcher(w.client, w.restMapper)
jobSR := helmStatusReaders.NewCustomJobStatusReader(w.restMapper)
podSR := helmStatusReaders.NewCustomPodStatusReader(w.restMapper)
// We don't want to wait on any other resources as watchUntilReady is only for Helm hooks.
@ -97,7 +103,7 @@ func (w *statusWaiter) Wait(resourceList ResourceList, timeout time.Duration) er
ctx, cancel := w.contextWithTimeout(w.waitCtx, timeout)
defer cancel()
w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout)
sw := watcher.NewDefaultStatusWatcher(w.client, w.restMapper)
sw := getStatusWatcher(w.client, w.restMapper)
sw.StatusReader = statusreaders.NewStatusReader(w.restMapper, w.readers...)
return w.wait(ctx, resourceList, sw)
}
@ -109,7 +115,7 @@ func (w *statusWaiter) WaitWithJobs(resourceList ResourceList, timeout time.Dura
ctx, cancel := w.contextWithTimeout(w.waitWithJobsCtx, timeout)
defer cancel()
w.Logger().Debug("waiting for resources", "count", len(resourceList), "timeout", timeout)
sw := watcher.NewDefaultStatusWatcher(w.client, w.restMapper)
sw := getStatusWatcher(w.client, w.restMapper)
newCustomJobStatusReader := helmStatusReaders.NewCustomJobStatusReader(w.restMapper)
readers := append([]engine.StatusReader(nil), w.readers...)
readers = append(readers, newCustomJobStatusReader)
@ -125,7 +131,7 @@ func (w *statusWaiter) WaitForDelete(resourceList ResourceList, timeout time.Dur
ctx, cancel := w.contextWithTimeout(w.waitForDeleteCtx, timeout)
defer cancel()
w.Logger().Debug("waiting for resources to be deleted", "count", len(resourceList), "timeout", timeout)
sw := watcher.NewDefaultStatusWatcher(w.client, w.restMapper)
sw := getStatusWatcher(w.client, w.restMapper)
return w.waitForDelete(ctx, resourceList, sw)
}
@ -161,7 +167,15 @@ func (w *statusWaiter) waitForDelete(ctx context.Context, resourceList ResourceL
rs.Identifier.GroupKind.Kind, rs.Identifier.Namespace, rs.Identifier.Name, rs.Status, rs.Message))
}
if err := ctx.Err(); err != nil {
errs = append(errs, err)
// context.Canceled and other non-deadline errors always propagate: they signal an
// external interruption regardless of resource state.
// context.DeadlineExceeded is only added when there are resource-specific errors;
// if all resources are Unknown or NotFound the timeout is not itself a failure for
// a delete wait (e.g. resources deleted before the watch started stay Unknown in
// the fake client but are effectively gone).
if !errors.Is(err, context.DeadlineExceeded) || len(errs) > 0 {
errs = append(errs, err)
}
}
if len(errs) > 0 {
return errors.Join(errs...)
@ -234,6 +248,7 @@ func statusObserver(cancel context.CancelFunc, desired status.Status, logger *sl
return func(statusCollector *collector.ResourceStatusCollector, _ event.Event) {
var rss []*event.ResourceStatus
var nonDesiredResources []*event.ResourceStatus
var unknownSkipped int
for _, rs := range statusCollector.ResourceStatuses {
if rs == nil {
continue
@ -241,6 +256,7 @@ func statusObserver(cancel context.CancelFunc, desired status.Status, logger *sl
// If a resource is already deleted before waiting has started, it will show as unknown.
// This check ensures we don't wait forever for a resource that is already deleted.
if rs.Status == status.UnknownStatus && desired == status.NotFoundStatus {
unknownSkipped++
continue
}
// Failed is a terminal state. This check ensures we don't wait forever for a resource
@ -254,6 +270,14 @@ func statusObserver(cancel context.CancelFunc, desired status.Status, logger *sl
}
}
// During informer initialization there is a brief window where existing resources
// appear as Unknown before their real status is delivered. If every resource was
// skipped as Unknown, we cannot yet distinguish "all deleted" from "not yet synced",
// so hold off on the early-cancel to avoid a spurious success or premature exit.
if unknownSkipped > 0 && len(rss) == 0 {
return
}
if aggregator.AggregateStatus(rss, desired) == desired {
logger.Debug("all resources achieved desired status", "desiredStatus", desired, "resourceCount", len(rss))
cancel()

@ -43,14 +43,12 @@ func extractChartMeta(chartData []byte) (*chart.Metadata, error) {
// generateOCIAnnotations will generate OCI annotations to include within the OCI manifest
func generateOCIAnnotations(meta *chart.Metadata, creationTime string) map[string]string {
// Get annotations from Chart attributes
ociAnnotations := generateChartOCIAnnotations(meta, creationTime)
// Copy Chart annotations
annotations:
for chartAnnotationKey, chartAnnotationValue := range meta.Annotations {
// Avoid overriding key properties
for _, immutableOciKey := range immutableOciAnnotations {
if immutableOciKey == chartAnnotationKey {
@ -88,7 +86,6 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[
var maintainerSb strings.Builder
for maintainerIdx, maintainer := range meta.Maintainers {
if len(maintainer.Name) > 0 {
maintainerSb.WriteString(maintainer.Name)
}
@ -102,11 +99,9 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[
if maintainerIdx < len(meta.Maintainers)-1 {
maintainerSb.WriteString(", ")
}
}
chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationAuthors, maintainerSb.String())
}
return chartOCIAnnotations
@ -114,7 +109,6 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[
// addToMap takes an existing map and adds an item if the value is not empty
func addToMap(inputMap map[string]string, newKey string, newValue string) map[string]string {
// Add item to map if its
if len(strings.TrimSpace(newValue)) > 0 {
inputMap[newKey] = newValue

@ -27,7 +27,6 @@ import (
)
func TestGenerateOCIChartAnnotations(t *testing.T) {
nowString := time.Now().Format(time.RFC3339)
tests := []struct {
@ -147,18 +146,15 @@ func TestGenerateOCIChartAnnotations(t *testing.T) {
}
for _, tt := range tests {
result := generateChartOCIAnnotations(tt.chart, nowString)
if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
}
}
}
func TestGenerateOCIAnnotations(t *testing.T) {
nowString := time.Now().Format(time.RFC3339)
tests := []struct {
@ -221,18 +217,15 @@ func TestGenerateOCIAnnotations(t *testing.T) {
}
for _, tt := range tests {
result := generateOCIAnnotations(tt.chart, nowString)
if !reflect.DeepEqual(tt.expect, result) {
t.Errorf("%s: expected map %v, got %v", tt.name, tt.expect, result)
}
}
}
func TestGenerateOCICreatedAnnotations(t *testing.T) {
nowTime := time.Now()
nowTimeString := nowTime.Format(time.RFC3339)
@ -268,7 +261,5 @@ func TestGenerateOCICreatedAnnotations(t *testing.T) {
if !nowTime.Before(createdTimeAnnotation) {
t.Errorf("%s annotation with value '%s' not configured properly. Annotation value is not after %s", ocispec.AnnotationCreated, result[ocispec.AnnotationCreated], nowTimeString)
}
}
}

@ -819,7 +819,6 @@ func (c *Client) Tags(ref string) ([]string, error) {
}
return tags, nil
}
// Resolve a reference to a descriptor.
@ -913,7 +912,6 @@ func (c *Client) ValidateReference(ref, version string, u *url.URL) (string, *ur
func (c *Client) tagManifest(ctx context.Context, memoryStore *memory.Store,
configDescriptor ocispec.Descriptor, layers []ocispec.Descriptor,
ociAnnotations map[string]string, parsedRef reference) (ocispec.Descriptor, error) {
manifest := ocispec.Manifest{
Versioned: specs.Versioned{SchemaVersion: 2},
Config: configDescriptor,

@ -17,7 +17,6 @@ limitations under the License.
package registry
import (
"errors"
"os"
"testing"
@ -43,12 +42,12 @@ func (suite *HTTPRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptPlainText(true))
suite.NotNil(err, "error logging into registry with bad credentials")
suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptPlainText(true))
suite.Nil(err, "no error logging into registry with good credentials")
suite.Require().NoError(err, "no error logging into registry with good credentials")
}
func (suite *HTTPRegistryClientTestSuite) Test_1_Push() {
@ -68,15 +67,15 @@ func (suite *HTTPRegistryClientTestSuite) Test_4_ManInTheMiddle() {
// returns content that does not match the expected digest
_, err := suite.RegistryClient.Pull(ref)
suite.NotNil(err)
suite.True(errors.Is(err, content.ErrMismatchedDigest))
suite.Require().Error(err)
suite.ErrorIs(err, content.ErrMismatchedDigest)
}
func (suite *HTTPRegistryClientTestSuite) Test_5_ImageIndex() {
ref := suite.FakeRegistryHost + "/testrepo/image-index:0.1.0"
_, err := suite.RegistryClient.Pull(ref)
suite.Nil(err)
suite.Require().NoError(err)
}
func TestHTTPRegistryClientTestSuite(t *testing.T) {

@ -41,12 +41,12 @@ func (suite *InsecureTLSRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptInsecure(true))
suite.NotNil(err, "error logging into registry with bad credentials")
suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true))
suite.Nil(err, "no error logging into registry with good credentials")
suite.Require().NoError(err, "no error logging into registry with good credentials")
}
func (suite *InsecureTLSRegistryClientTestSuite) Test_1_Push() {
@ -65,11 +65,11 @@ func (suite *InsecureTLSRegistryClientTestSuite) Test_4_Logout() {
err := suite.RegistryClient.Logout("this-host-aint-real:5000")
if err != nil {
// credential backend for mac generates an error
suite.NotNil(err, "failed to delete the credential for this-host-aint-real:5000")
suite.Require().Error(err, "failed to delete the credential for this-host-aint-real:5000")
}
err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry")
suite.Require().NoError(err, "no error logging out of registry")
}
func TestInsecureTLSRegistryClientTestSuite(t *testing.T) {

@ -43,26 +43,26 @@ func (suite *TLSRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA))
suite.NotNil(err, "error logging into registry with bad credentials")
suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA))
suite.Nil(err, "no error logging into registry with good credentials")
suite.Require().NoError(err, "no error logging into registry with good credentials")
}
func (suite *TLSRegistryClientTestSuite) Test_1_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptTLSClientConfigFromConfig(&tls.Config{}))
suite.NotNil(err, "error logging into registry with bad credentials")
suite.Require().Error(err, "error logging into registry with bad credentials")
// Create a *tls.Config from tlsCert, tlsKey, and tlsCA.
cert, err := tls.LoadX509KeyPair(tlsCert, tlsKey)
suite.Nil(err, "error loading x509 key pair")
suite.Require().NoError(err, "error loading x509 key pair")
rootCAs := x509.NewCertPool()
caCert, err := os.ReadFile(tlsCA)
suite.Nil(err, "error reading CA certificate")
suite.Require().NoError(err, "error reading CA certificate")
rootCAs.AppendCertsFromPEM(caCert)
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
@ -72,7 +72,7 @@ func (suite *TLSRegistryClientTestSuite) Test_1_Login() {
err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword),
LoginOptTLSClientConfigFromConfig(conf))
suite.Nil(err, "no error logging into registry with good credentials")
suite.Require().NoError(err, "no error logging into registry with good credentials")
}
func (suite *TLSRegistryClientTestSuite) Test_1_Push() {
@ -91,11 +91,11 @@ func (suite *TLSRegistryClientTestSuite) Test_4_Logout() {
err := suite.RegistryClient.Logout("this-host-aint-real:5000")
if err != nil {
// credential backend for mac generates an error
suite.NotNil(err, "failed to delete the credential for this-host-aint-real:5000")
suite.Require().Error(err, "failed to delete the credential for this-host-aint-real:5000")
}
err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry")
suite.Require().NoError(err, "no error logging out of registry")
}
func TestTLSRegistryClientTestSuite(t *testing.T) {

@ -107,26 +107,26 @@ func setup(suite *TestRegistry, tlsEnabled, insecure bool) {
TLSClientConfig: tlsConf,
},
}
suite.Nil(err, "no error loading tls config")
suite.Require().NoError(err, "no error loading tls config")
opts = append(opts, ClientOptHTTPClient(httpClient))
} else {
opts = append(opts, ClientOptPlainHTTP())
}
suite.RegistryClient, err = NewClient(opts...)
suite.Nil(err, "no error creating registry client")
suite.Require().NoError(err, "no error creating registry client")
// create htpasswd file (w BCrypt, which is required)
pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost)
suite.Nil(err, "no error generating bcrypt password for test htpasswd file")
suite.Require().NoError(err, "no error generating bcrypt password for test htpasswd file")
htpasswdPath := filepath.Join(suite.WorkspaceDir, testHtpasswdFileBasename)
err = os.WriteFile(htpasswdPath, fmt.Appendf(nil, "%s:%s\n", testUsername, string(pwBytes)), 0644)
suite.Nil(err, "no error creating test htpasswd file")
suite.Require().NoError(err, "no error creating test htpasswd file")
// Registry config
config := &configuration.Configuration{}
ln, err := net.Listen("tcp", "127.0.0.1:0")
suite.Nil(err, "no error finding free port for test registry")
suite.Require().NoError(err, "no error finding free port for test registry")
defer func() { _ = ln.Close() }()
// Change the registry host to another host which is not localhost.
@ -159,7 +159,7 @@ func setup(suite *TestRegistry, tlsEnabled, insecure bool) {
}
}
suite.dockerRegistry, err = registry.NewRegistry(context.Background(), config)
suite.Nil(err, "no error creating test registry")
suite.Require().NoError(err, "no error creating test registry")
suite.FakeRegistryHost = initFakeRegistryTestServer()
suite.CompromisedRegistryHost = initCompromisedRegistryTestServer()
@ -380,67 +380,66 @@ func initFakeRegistryTestServer() string {
}
func testPush(suite *TestRegistry) {
testingChartCreationTime := "1977-09-02T22:04:05Z"
// Bad bytes
ref := suite.DockerRegistryHost + "/testrepo/testchart:1.2.3"
_, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-chart bytes")
suite.Require().Error(err, "error pushing non-chart bytes")
// Load a test chart
chartData, err := os.ReadFile("../repo/v1/repotest/testdata/examplechart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
// non-strict ref (chart name)
ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad basename)")
suite.Require().Error(err, "error pushing non-strict ref (bad basename)")
// non-strict ref (chart name), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled")
suite.Require().NoError(err, "no error pushing non-strict ref (bad basename), with strict mode disabled")
// non-strict ref (chart version)
ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad tag)")
suite.Require().Error(err, "error pushing non-strict ref (bad tag)")
// non-strict ref (chart version), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled")
suite.Require().NoError(err, "no error pushing non-strict ref (bad tag), with strict mode disabled")
// basic push, good ref
chartData, err = os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref")
suite.Require().NoError(err, "no error pushing good ref")
_, err = suite.RegistryClient.Pull(ref)
suite.Nil(err, "no error pulling a simple chart")
suite.Require().NoError(err, "no error pulling a simple chart")
// Load another test chart
chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
// Load prov file
provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov")
suite.Nil(err, "no error loading test prov")
suite.Require().NoError(err, "no error loading test prov")
// push with prov
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref with prov")
suite.Require().NoError(err, "no error pushing good ref with prov")
_, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.Nil(err, "no error pulling a simple chart")
suite.Require().NoError(err, "no error pulling a simple chart")
// Validate the output
// Note: these digests/sizes etc may change if the test chart/prov files are modified,
@ -470,50 +469,50 @@ func testPull(suite *TestRegistry) {
// bad/missing ref
ref := suite.DockerRegistryHost + "/testrepo/no-existy:1.2.3"
_, err := suite.RegistryClient.Pull(ref)
suite.NotNil(err, "error on bad/missing ref")
suite.Require().Error(err, "error on bad/missing ref")
// Load test chart (to build ref pushed in previous test)
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
// Simple pull, chart only
_, err = suite.RegistryClient.Pull(ref)
suite.Nil(err, "no error pulling a simple chart")
suite.Require().NoError(err, "no error pulling a simple chart")
// Simple pull with prov (no prov uploaded)
_, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.NotNil(err, "error pulling a chart with prov when no prov exists")
suite.Require().Error(err, "error pulling a chart with prov when no prov exists")
// Simple pull with prov, ignoring missing prov
_, err = suite.RegistryClient.Pull(ref,
PullOptWithProv(true),
PullOptIgnoreMissingProv(true))
suite.Nil(err,
suite.Require().NoError(err,
"no error pulling a chart with prov when no prov exists, ignoring missing")
// Load test chart (to build ref pushed in previous test)
chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
// Load prov file
provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov")
suite.Nil(err, "no error loading test prov")
suite.Require().NoError(err, "no error loading test prov")
// no chart and no prov causes error
_, err = suite.RegistryClient.Pull(ref,
PullOptWithChart(false),
PullOptWithProv(false))
suite.NotNil(err, "error on both no chart and no prov")
suite.Require().Error(err, "error on both no chart and no prov")
// full pull with chart and prov
result, err := suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.Require().Nil(err, "no error pulling a chart with prov")
suite.Require().NoError(err, "no error pulling a chart with prov")
// Validate the output
// Note: these digests/sizes etc may change if the test chart/prov files are modified,
@ -548,13 +547,13 @@ func testPull(suite *TestRegistry) {
func testTags(suite *TestRegistry) {
// Load test chart (to build ref pushed in previous test)
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart")
suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta")
suite.Require().NoError(err, "no error extracting chart meta")
ref := fmt.Sprintf("%s/testrepo/%s", suite.DockerRegistryHost, meta.Name)
// Query for tags and validate length
tags, err := suite.RegistryClient.Tags(ref)
suite.Nil(err, "no error retrieving tags")
suite.Require().NoError(err, "no error retrieving tags")
suite.Equal(1, len(tags))
}

@ -26,7 +26,6 @@ import (
)
func TestSortManifests(t *testing.T) {
data := []struct {
name []string
path string
@ -183,7 +182,6 @@ metadata:
if !reflect.DeepEqual(expectedHooks, out.Events) {
t.Errorf("expected events: %v but got: %v", expectedHooks, out.Events)
}
}
}
if !found {

@ -173,7 +173,6 @@ func WithInsecureSkipTLSVerify(insecureSkipTLSVerify bool) FindChartInRepoURLOpt
// FindChartInRepoURL finds chart in chart repository pointed by repoURL
// without adding repo to repositories
func FindChartInRepoURL(repoURL string, chartName string, getters getter.Providers, options ...FindChartInRepoURLOption) (string, error) {
opts := findChartInRepoURLOptions{}
for _, option := range options {
option(&opts)

@ -126,7 +126,6 @@ func TestConcurrencyDownloadIndex(t *testing.T) {
// 2) read index.yaml via LoadIndexFile (read operation).
// This checks for race conditions and ensures correct behavior under concurrent read/write access.
for range 150 {
wg.Go(func() {
idx, err := repo.DownloadIndexFile()
if err != nil {
@ -234,7 +233,6 @@ func TestFindChartInRepoURL(t *testing.T) {
}
func TestErrorFindChartInRepoURL(t *testing.T) {
g := getter.All(&cli.EnvSettings{
RepositoryCache: t.TempDir(),
})

@ -140,7 +140,6 @@ func TestIndexFile(t *testing.T) {
}
func TestLoadIndex(t *testing.T) {
tests := []struct {
Name string
Filename string
@ -250,7 +249,6 @@ func TestMerge(t *testing.T) {
if v := vs[1]; v.Version != "0.2.0" {
t.Errorf("Expected %q version to be 0.2.0, got %s", v.Name, v.Version)
}
}
func TestDownloadIndexFile(t *testing.T) {
@ -642,7 +640,6 @@ func TestIgnoreSkippableChartValidationError(t *testing.T) {
if !errors.Is(tc.Input, result) {
t.Error("expected the result equal to input")
}
})
}
}

@ -143,7 +143,6 @@ func TestNewTempServer(t *testing.T) {
if res.StatusCode != http.StatusOK {
t.Errorf("Expected 200, got %d", res.StatusCode)
}
}
{
@ -203,7 +202,6 @@ func TestNewTempServer(t *testing.T) {
}
})
}
}
func TestNewTempServer_TLS(t *testing.T) {

@ -35,8 +35,7 @@ func MakeTestTLSConfig(t *testing.T, path string) *tls.Config {
tlsutil.WithCertKeyPairFiles(pub, priv),
tlsutil.WithCAFile(ca),
)
//require.Nil(t, err, err.Error())
require.Nil(t, err)
require.NoError(t, err)
tlsConf.ServerName = "helm.sh"

@ -300,5 +300,4 @@ func TestMemoryDelete(t *testing.T) {
t.Logf("Name: %s, Version: %d", rac.Name(), rac.Version())
}
}
}

@ -134,7 +134,6 @@ func (s *SQL) checkAlreadyApplied(migrations []*migrate.Migration) bool {
}
func (s *SQL) ensureDBSetup() error {
migrations := &migrate.MemoryMigrationSource{
Migrations: []*migrate.Migration{
{

@ -330,7 +330,6 @@ func (t *parser) keyIndex() (int, error) {
}
// v should be the index
return strconv.Atoi(string(v))
}
func (t *parser) listItem(list []any, i, nestedNameLevel int) ([]any, error) {

Loading…
Cancel
Save