summaryrefslogtreecommitdiff
path: root/vendor/helm.sh
diff options
context:
space:
mode:
authorShelley-BaoYue <baoyue2@huawei.com>2023-05-25 17:23:57 +0800
committerfisherxu <xufei40@huawei.com>2023-07-01 03:57:26 +0800
commit95bc4f55be0c27fd3fa4a9433eb689979dd2f913 (patch)
treed3eb7e3c77a64e21565eeb971f0783aa799cbcaf /vendor/helm.sh
parentMerge pull request #4734 from wenchajun/kubectl-attach (diff)
downloadkubeedge-95bc4f55be0c27fd3fa4a9433eb689979dd2f913.tar.gz
update k8s version to 1.24
Signed-off-by: Shelley-BaoYue <baoyue2@huawei.com>
Diffstat (limited to 'vendor/helm.sh')
-rw-r--r--vendor/helm.sh/helm/v3/internal/experimental/registry/util.go56
-rw-r--r--vendor/helm.sh/helm/v3/internal/resolver/resolver.go56
-rw-r--r--vendor/helm.sh/helm/v3/internal/sympath/walk.go2
-rw-r--r--vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename.go2
-rw-r--r--vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename_windows.go2
-rw-r--r--vendor/helm.sh/helm/v3/internal/version/version.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/action.go3
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/install.go62
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/lint.go11
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/pull.go10
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/push.go70
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/registry_login.go43
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/registry_logout.go38
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/rollback.go5
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/show.go12
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/upgrade.go32
-rw-r--r--vendor/helm.sh/helm/v3/pkg/action/validate.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go59
-rw-r--r--vendor/helm.sh/helm/v3/pkg/chartutil/dependencies.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/chartutil/validate_name.go15
-rw-r--r--vendor/helm.sh/helm/v3/pkg/cli/environment.go7
-rw-r--r--vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go46
-rw-r--r--vendor/helm.sh/helm/v3/pkg/downloader/manager.go27
-rw-r--r--vendor/helm.sh/helm/v3/pkg/getter/getter.go11
-rw-r--r--vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go31
-rw-r--r--vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go12
-rw-r--r--vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_darwin.go1
-rw-r--r--vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_unix.go1
-rw-r--r--vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_windows.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/kube/client.go21
-rw-r--r--vendor/helm.sh/helm/v3/pkg/kube/factory.go12
-rw-r--r--vendor/helm.sh/helm/v3/pkg/kube/ready.go16
-rw-r--r--vendor/helm.sh/helm/v3/pkg/lint/rules/template.go6
-rw-r--r--vendor/helm.sh/helm/v3/pkg/postrender/exec.go7
-rw-r--r--vendor/helm.sh/helm/v3/pkg/provenance/sign.go27
-rw-r--r--vendor/helm.sh/helm/v3/pkg/pusher/doc.go (renamed from vendor/helm.sh/helm/v3/pkg/gates/gates.go)29
-rw-r--r--vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go106
-rw-r--r--vendor/helm.sh/helm/v3/pkg/pusher/pusher.go95
-rw-r--r--vendor/helm.sh/helm/v3/pkg/registry/client.go (renamed from vendor/helm.sh/helm/v3/internal/experimental/registry/client.go)232
-rw-r--r--vendor/helm.sh/helm/v3/pkg/registry/constants.go (renamed from vendor/helm.sh/helm/v3/internal/experimental/registry/constants.go)4
-rw-r--r--vendor/helm.sh/helm/v3/pkg/registry/util.go131
-rw-r--r--vendor/helm.sh/helm/v3/pkg/releaseutil/kind_sorter.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/storage/driver/util.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/storage/storage.go2
-rw-r--r--vendor/helm.sh/helm/v3/pkg/strvals/parser.go7
-rw-r--r--vendor/helm.sh/helm/v3/pkg/uploader/chart_uploader.go58
-rw-r--r--vendor/helm.sh/helm/v3/pkg/uploader/doc.go (renamed from vendor/helm.sh/helm/v3/pkg/gates/doc.go)6
47 files changed, 1115 insertions, 270 deletions
diff --git a/vendor/helm.sh/helm/v3/internal/experimental/registry/util.go b/vendor/helm.sh/helm/v3/internal/experimental/registry/util.go
deleted file mode 100644
index 257e7af87..000000000
--- a/vendor/helm.sh/helm/v3/internal/experimental/registry/util.go
+++ /dev/null
@@ -1,56 +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 registry // import "helm.sh/helm/v3/internal/experimental/registry"
-
-import (
- "bytes"
- "context"
- "fmt"
- "io"
- "strings"
-
- "github.com/sirupsen/logrus"
- orascontext "oras.land/oras-go/pkg/context"
-
- "helm.sh/helm/v3/pkg/chart"
- "helm.sh/helm/v3/pkg/chart/loader"
-)
-
-// IsOCI determines whether or not a URL is to be treated as an OCI URL
-func IsOCI(url string) bool {
- return strings.HasPrefix(url, fmt.Sprintf("%s://", OCIScheme))
-}
-
-// extractChartMeta is used to extract a chart metadata from a byte array
-func extractChartMeta(chartData []byte) (*chart.Metadata, error) {
- ch, err := loader.LoadArchive(bytes.NewReader(chartData))
- if err != nil {
- return nil, err
- }
- return ch.Metadata, nil
-}
-
-// ctx retrieves a fresh context.
-// disable verbose logging coming from ORAS (unless debug is enabled)
-func ctx(out io.Writer, debug bool) context.Context {
- if !debug {
- return orascontext.Background()
- }
- ctx := orascontext.WithLoggerFromWriter(context.Background(), out)
- orascontext.GetLogger(ctx).Logger.SetLevel(logrus.DebugLevel)
- return ctx
-}
diff --git a/vendor/helm.sh/helm/v3/internal/resolver/resolver.go b/vendor/helm.sh/helm/v3/internal/resolver/resolver.go
index 70ce6a55b..5e8921f96 100644
--- a/vendor/helm.sh/helm/v3/internal/resolver/resolver.go
+++ b/vendor/helm.sh/helm/v3/internal/resolver/resolver.go
@@ -18,6 +18,7 @@ package resolver
import (
"bytes"
"encoding/json"
+ "fmt"
"os"
"path/filepath"
"strings"
@@ -26,28 +27,27 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
- "helm.sh/helm/v3/pkg/gates"
"helm.sh/helm/v3/pkg/helmpath"
"helm.sh/helm/v3/pkg/provenance"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/repo"
)
-const FeatureGateOCI = gates.Gate("HELM_EXPERIMENTAL_OCI")
-
// Resolver resolves dependencies from semantic version ranges to a particular version.
type Resolver struct {
- chartpath string
- cachepath string
+ chartpath string
+ cachepath string
+ registryClient *registry.Client
}
-// New creates a new resolver for a given chart and a given helm home.
-func New(chartpath, cachepath string) *Resolver {
+// New creates a new resolver for a given chart, helm home and registry client.
+func New(chartpath, cachepath string, registryClient *registry.Client) *Resolver {
return &Resolver{
- chartpath: chartpath,
- cachepath: cachepath,
+ chartpath: chartpath,
+ cachepath: cachepath,
+ registryClient: registryClient,
}
}
@@ -135,9 +135,36 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string
found = false
} else {
version = d.Version
- if !FeatureGateOCI.IsEnabled() {
- return nil, errors.Wrapf(FeatureGateOCI.Error(),
- "repository %s is an OCI registry", d.Repository)
+
+ // Check to see if an explicit version has been provided
+ _, err := semver.NewVersion(version)
+
+ // Use an explicit version, otherwise search for tags
+ if err == nil {
+ vs = []*repo.ChartVersion{{
+ Metadata: &chart.Metadata{
+ Version: version,
+ },
+ }}
+
+ } else {
+ // Retrieve list of tags for repository
+ ref := fmt.Sprintf("%s/%s", strings.TrimPrefix(d.Repository, fmt.Sprintf("%s://", registry.OCIScheme)), d.Name)
+ tags, err := r.registryClient.Tags(ref)
+ if err != nil {
+ return nil, errors.Wrapf(err, "could not retrieve list of tags for repository %s", d.Repository)
+ }
+
+ vs = make(repo.ChartVersions, len(tags))
+ for ti, t := range tags {
+ // Mock chart version objects
+ version := &repo.ChartVersion{
+ Metadata: &chart.Metadata{
+ Version: t,
+ },
+ }
+ vs[ti] = version
+ }
}
}
@@ -149,7 +176,8 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string
// The version are already sorted and hence the first one to satisfy the constraint is used
for _, ver := range vs {
v, err := semver.NewVersion(ver.Version)
- if err != nil || len(ver.URLs) == 0 {
+ // OCI does not need URLs
+ if err != nil || (!registry.IsOCI(d.Repository) && len(ver.URLs) == 0) {
// Not a legit entry.
continue
}
diff --git a/vendor/helm.sh/helm/v3/internal/sympath/walk.go b/vendor/helm.sh/helm/v3/internal/sympath/walk.go
index 752526fe9..a276cfeff 100644
--- a/vendor/helm.sh/helm/v3/internal/sympath/walk.go
+++ b/vendor/helm.sh/helm/v3/internal/sympath/walk.go
@@ -71,7 +71,7 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
if err != nil {
return errors.Wrapf(err, "error evaluating symlink %s", path)
}
- log.Printf("found symbolic link in path: %s resolves to %s", path, resolved)
+ log.Printf("found symbolic link in path: %s resolves to %s. Contents of linked file included and used", path, resolved)
if info, err = os.Lstat(resolved); err != nil {
return err
}
diff --git a/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename.go b/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename.go
index 0bb600949..a3e5e56a6 100644
--- a/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename.go
+++ b/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename.go
@@ -1,4 +1,4 @@
-// +build !windows
+//go:build !windows
/*
Copyright (c) for portions of rename.go are held by The Go Authors, 2016 and are provided under
diff --git a/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename_windows.go b/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename_windows.go
index 14f017d09..a377720a6 100644
--- a/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename_windows.go
+++ b/vendor/helm.sh/helm/v3/internal/third_party/dep/fs/rename_windows.go
@@ -1,4 +1,4 @@
-// +build windows
+//go:build windows
/*
Copyright (c) for portions of rename_windows.go are held by The Go Authors, 2016 and are provided under
diff --git a/vendor/helm.sh/helm/v3/internal/version/version.go b/vendor/helm.sh/helm/v3/internal/version/version.go
index 201eee359..6919e29d8 100644
--- a/vendor/helm.sh/helm/v3/internal/version/version.go
+++ b/vendor/helm.sh/helm/v3/internal/version/version.go
@@ -29,7 +29,7 @@ var (
//
// Increment major number for new feature additions and behavioral changes.
// Increment minor number for bug fixes and performance enhancements.
- version = "v3.7"
+ version = "v3.9"
// metadata is extra build time data
metadata = ""
diff --git a/vendor/helm.sh/helm/v3/pkg/action/action.go b/vendor/helm.sh/helm/v3/pkg/action/action.go
index f093ed7f8..82760250f 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/action.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/action.go
@@ -32,12 +32,12 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/engine"
"helm.sh/helm/v3/pkg/kube"
"helm.sh/helm/v3/pkg/postrender"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/storage"
@@ -272,6 +272,7 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
Major: kubeVersion.Major,
Minor: kubeVersion.Minor,
},
+ HelmVersion: chartutil.DefaultCapabilities.HelmVersion,
}
return cfg.Capabilities, nil
}
diff --git a/vendor/helm.sh/helm/v3/pkg/action/install.go b/vendor/helm.sh/helm/v3/pkg/action/install.go
index b84a57271..3872ed5c9 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/install.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/install.go
@@ -38,7 +38,6 @@ import (
"k8s.io/cli-runtime/pkg/resource"
"sigs.k8s.io/yaml"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
@@ -47,6 +46,7 @@ import (
"helm.sh/helm/v3/pkg/kube"
kubefake "helm.sh/helm/v3/pkg/kube/fake"
"helm.sh/helm/v3/pkg/postrender"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/repo"
@@ -54,13 +54,6 @@ import (
"helm.sh/helm/v3/pkg/storage/driver"
)
-// releaseNameMaxLen is the maximum length of a release name.
-//
-// As of Kubernetes 1.4, the max limit on a name is 63 chars. We reserve 10 for
-// charts to add data. Effectively, that gives us 53 chars.
-// See https://github.com/helm/helm/issues/1528
-const releaseNameMaxLen = 53
-
// NOTESFILE_SUFFIX that we want to treat special. It goes through the templating engine
// but it's not a yaml file (resource) hence can't have hooks, etc. And the user actually
// wants to see this file after rendering in the status command. However, it must be a suffix
@@ -124,13 +117,20 @@ type ChartPathOptions struct {
Username string // --username
Verify bool // --verify
Version string // --version
+
+ // registryClient provides a registry client but is not added with
+ // options from a flag
+ registryClient *registry.Client
}
// NewInstall creates a new Install object with the given configuration.
func NewInstall(cfg *Configuration) *Install {
- return &Install{
+ in := &Install{
cfg: cfg,
}
+ in.ChartPathOptions.registryClient = cfg.RegistryClient
+
+ return in
}
func (i *Install) installCRDs(crds []chart.CRD) error {
@@ -198,6 +198,10 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
return nil, err
}
+ if err := chartutil.ProcessDependencies(chrt, vals); err != nil {
+ return nil, err
+ }
+
// Pre-install anything in the crd/ directory. We do this before Helm
// contacts the upstream server and builds the capabilities object.
if crds := chrt.CRDObjects(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 {
@@ -226,10 +230,6 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
i.cfg.Log("API Version list given outside of client only mode, this list will be ignored")
}
- if err := chartutil.ProcessDependencies(chrt, vals); err != nil {
- return nil, err
- }
-
// Make sure if Atomic is set, that wait is set as well. This makes it so
// the user doesn't have to specify both
i.Wait = i.Wait || i.Atomic
@@ -344,8 +344,10 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
return rel, err
}
rChan := make(chan resultMessage)
+ doneChan := make(chan struct{})
+ defer close(doneChan)
go i.performInstall(rChan, rel, toBeAdopted, resources)
- go i.handleContext(ctx, rChan, rel)
+ go i.handleContext(ctx, rChan, doneChan, rel)
result := <-rChan
//start preformInstall go routine
return result.r, result.e
@@ -416,12 +418,14 @@ func (i *Install) performInstall(c chan<- resultMessage, rel *release.Release, t
i.reportToRun(c, rel, nil)
}
-func (i *Install) handleContext(ctx context.Context, c chan<- resultMessage, rel *release.Release) {
- go func() {
- <-ctx.Done()
+func (i *Install) handleContext(ctx context.Context, c chan<- resultMessage, done chan struct{}, rel *release.Release) {
+ select {
+ case <-ctx.Done():
err := ctx.Err()
i.reportToRun(c, rel, err)
- }()
+ case <-done:
+ return
+ }
}
func (i *Install) reportToRun(c chan<- resultMessage, rel *release.Release, err error) {
i.Lock.Lock()
@@ -458,14 +462,10 @@ func (i *Install) failRelease(rel *release.Release, err error) (*release.Release
// - used by a deleted release, and i.Replace is false
func (i *Install) availableName() error {
start := i.ReleaseName
- if start == "" {
- return errors.New("name is required")
- }
- if len(start) > releaseNameMaxLen {
- return errors.Errorf("release name %q exceeds max length of %d", start, releaseNameMaxLen)
+ if err := chartutil.ValidateReleaseName(start); err != nil {
+ return errors.Wrapf(err, "release name %q", start)
}
-
if i.DryRun {
return nil
}
@@ -673,6 +673,12 @@ OUTER:
//
// If 'verify' was set on ChartPathOptions, this will attempt to also verify the chart.
func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (string, error) {
+ // If there is no registry client and the name is in an OCI registry return
+ // an error and a lookup will not occur.
+ if registry.IsOCI(name) && c.registryClient == nil {
+ return "", fmt.Errorf("unable to lookup chart %q, missing registry client", name)
+ }
+
name = strings.TrimSpace(name)
version := strings.TrimSpace(c.Version)
@@ -703,13 +709,7 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
},
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
- }
-
- if registry.IsOCI(name) {
- if version == "" {
- return "", errors.New("version is explicitly required for OCI registries")
- }
- dl.Options = append(dl.Options, getter.WithTagName(version))
+ RegistryClient: c.registryClient,
}
if c.Verify {
diff --git a/vendor/helm.sh/helm/v3/pkg/action/lint.go b/vendor/helm.sh/helm/v3/pkg/action/lint.go
index bdb93dcc2..5b566e9d3 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/lint.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/lint.go
@@ -36,6 +36,7 @@ type Lint struct {
Strict bool
Namespace string
WithSubcharts bool
+ Quiet bool
}
// LintResult is the result of Lint
@@ -75,6 +76,16 @@ func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
return result
}
+// HasWaringsOrErrors checks is LintResult has any warnings or errors
+func HasWarningsOrErrors(result *LintResult) bool {
+ for _, msg := range result.Messages {
+ if msg.Severity > support.InfoSev {
+ return true
+ }
+ }
+ return false
+}
+
func lintChart(path string, vals map[string]interface{}, namespace string, strict bool) (support.Linter, error) {
var chartPath string
linter := support.Linter{}
diff --git a/vendor/helm.sh/helm/v3/pkg/action/pull.go b/vendor/helm.sh/helm/v3/pkg/action/pull.go
index 2f5127ea9..b4018869e 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/pull.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/pull.go
@@ -25,11 +25,11 @@ import (
"github.com/pkg/errors"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/repo"
)
@@ -87,18 +87,14 @@ func (p *Pull) Run(chartRef string) (string, error) {
getter.WithTLSClientConfig(p.CertFile, p.KeyFile, p.CaFile),
getter.WithInsecureSkipVerifyTLS(p.InsecureSkipTLSverify),
},
+ RegistryClient: p.cfg.RegistryClient,
RepositoryConfig: p.Settings.RepositoryConfig,
RepositoryCache: p.Settings.RepositoryCache,
}
if registry.IsOCI(chartRef) {
- if p.Version == "" {
- return out.String(), errors.Errorf("--version flag is explicitly required for OCI registries")
- }
-
c.Options = append(c.Options,
- getter.WithRegistryClient(p.cfg.RegistryClient),
- getter.WithTagName(p.Version))
+ getter.WithRegistryClient(p.cfg.RegistryClient))
}
if p.Verify {
diff --git a/vendor/helm.sh/helm/v3/pkg/action/push.go b/vendor/helm.sh/helm/v3/pkg/action/push.go
new file mode 100644
index 000000000..99d1beadc
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/action/push.go
@@ -0,0 +1,70 @@
+/*
+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 action
+
+import (
+ "strings"
+
+ "helm.sh/helm/v3/pkg/cli"
+ "helm.sh/helm/v3/pkg/pusher"
+ "helm.sh/helm/v3/pkg/registry"
+ "helm.sh/helm/v3/pkg/uploader"
+)
+
+// Push is the action for uploading a chart.
+//
+// It provides the implementation of 'helm push'.
+type Push struct {
+ Settings *cli.EnvSettings
+ cfg *Configuration
+}
+
+// PushOpt is a type of function that sets options for a push action.
+type PushOpt func(*Push)
+
+// WithPushConfig sets the cfg field on the push configuration object.
+func WithPushConfig(cfg *Configuration) PushOpt {
+ return func(p *Push) {
+ p.cfg = cfg
+ }
+}
+
+// NewPushWithOpts creates a new push, with configuration options.
+func NewPushWithOpts(opts ...PushOpt) *Push {
+ p := &Push{}
+ for _, fn := range opts {
+ fn(p)
+ }
+ return p
+}
+
+// Run executes 'helm push' against the given chart archive.
+func (p *Push) Run(chartRef string, remote string) (string, error) {
+ var out strings.Builder
+
+ c := uploader.ChartUploader{
+ Out: &out,
+ Pushers: pusher.All(p.Settings),
+ Options: []pusher.Option{},
+ }
+
+ if registry.IsOCI(remote) {
+ c.Options = append(c.Options, pusher.WithRegistryClient(p.cfg.RegistryClient))
+ }
+
+ return out.String(), c.UploadTo(chartRef, remote)
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/action/registry_login.go b/vendor/helm.sh/helm/v3/pkg/action/registry_login.go
new file mode 100644
index 000000000..68bcc7442
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/action/registry_login.go
@@ -0,0 +1,43 @@
+/*
+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 action
+
+import (
+ "io"
+
+ "helm.sh/helm/v3/pkg/registry"
+)
+
+// RegistryLogin performs a registry login operation.
+type RegistryLogin struct {
+ cfg *Configuration
+}
+
+// NewRegistryLogin creates a new RegistryLogin object with the given configuration.
+func NewRegistryLogin(cfg *Configuration) *RegistryLogin {
+ return &RegistryLogin{
+ cfg: cfg,
+ }
+}
+
+// Run executes the registry login operation
+func (a *RegistryLogin) Run(out io.Writer, hostname string, username string, password string, insecure bool) error {
+ return a.cfg.RegistryClient.Login(
+ hostname,
+ registry.LoginOptBasicAuth(username, password),
+ registry.LoginOptInsecure(insecure))
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/action/registry_logout.go b/vendor/helm.sh/helm/v3/pkg/action/registry_logout.go
new file mode 100644
index 000000000..69add4163
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/action/registry_logout.go
@@ -0,0 +1,38 @@
+/*
+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 action
+
+import (
+ "io"
+)
+
+// RegistryLogout performs a registry login operation.
+type RegistryLogout struct {
+ cfg *Configuration
+}
+
+// NewRegistryLogout creates a new RegistryLogout object with the given configuration.
+func NewRegistryLogout(cfg *Configuration) *RegistryLogout {
+ return &RegistryLogout{
+ cfg: cfg,
+ }
+}
+
+// Run executes the registry logout operation
+func (a *RegistryLogout) Run(out io.Writer, hostname string) error {
+ return a.cfg.RegistryClient.Logout(hostname)
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/action/rollback.go b/vendor/helm.sh/helm/v3/pkg/action/rollback.go
index f3f958f3d..dda8c700b 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/rollback.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/rollback.go
@@ -164,6 +164,11 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas
r.cfg.Log("rollback hooks disabled for %s", targetRelease.Name)
}
+ // It is safe to use "force" here because these are resources currently rendered by the chart.
+ err = target.Visit(setMetadataVisitor(targetRelease.Name, targetRelease.Namespace, true))
+ if err != nil {
+ return targetRelease, errors.Wrap(err, "unable to set metadata visitor from target release")
+ }
results, err := r.cfg.KubeClient.Update(current, target, r.Force)
if err != nil {
diff --git a/vendor/helm.sh/helm/v3/pkg/action/show.go b/vendor/helm.sh/helm/v3/pkg/action/show.go
index 1e3da3bdc..9ba85234d 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/show.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/show.go
@@ -64,12 +64,24 @@ type Show struct {
}
// NewShow creates a new Show object with the given configuration.
+// Deprecated: Use NewShowWithConfig
+// TODO Helm 4: Fold NewShowWithConfig back into NewShow
func NewShow(output ShowOutputFormat) *Show {
return &Show{
OutputFormat: output,
}
}
+// NewShowWithConfig creates a new Show object with the given configuration.
+func NewShowWithConfig(output ShowOutputFormat, cfg *Configuration) *Show {
+ sh := &Show{
+ OutputFormat: output,
+ }
+ sh.ChartPathOptions.registryClient = cfg.RegistryClient
+
+ return sh
+}
+
// Run executes 'helm show' against the given release.
func (s *Show) Run(chartpath string) (string, error) {
if s.chart == nil {
diff --git a/vendor/helm.sh/helm/v3/pkg/action/upgrade.go b/vendor/helm.sh/helm/v3/pkg/action/upgrade.go
index 27c1f01e7..690397d4a 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/upgrade.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/upgrade.go
@@ -112,18 +112,21 @@ type resultMessage struct {
// NewUpgrade creates a new Upgrade object with the given configuration.
func NewUpgrade(cfg *Configuration) *Upgrade {
- return &Upgrade{
+ up := &Upgrade{
cfg: cfg,
}
+ up.ChartPathOptions.registryClient = cfg.RegistryClient
+
+ return up
}
-// Run executes the upgrade on the given release
+// Run executes the upgrade on the given release.
func (u *Upgrade) Run(name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
ctx := context.Background()
return u.RunWithContext(ctx, name, chart, vals)
}
-// Run executes the upgrade on the given release with context.
+// 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) {
if err := u.cfg.KubeClient.IsReachable(); err != nil {
return nil, err
@@ -323,11 +326,11 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR
rChan := make(chan resultMessage)
ctxChan := make(chan resultMessage)
doneChan := make(chan interface{})
+ defer close(doneChan)
go u.releasingUpgrade(rChan, upgradedRelease, current, target, originalRelease)
go u.handleContext(ctx, doneChan, ctxChan, upgradedRelease)
select {
case result := <-rChan:
- doneChan <- true
return result.r, result.e
case result := <-ctxChan:
return result.r, result.e
@@ -348,17 +351,15 @@ 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) {
- go func() {
- select {
- case <-ctx.Done():
- err := ctx.Err()
+ select {
+ case <-ctx.Done():
+ err := ctx.Err()
- // when the atomic flag is set the ongoing release finish first and doesn't give time for the rollback happens.
- u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err)
- case <-done:
- return
- }
- }()
+ // when the atomic flag is set the ongoing release finish first and doesn't give time for the rollback happens.
+ u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err)
+ case <-done:
+ return
+ }
}
func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release) {
// pre-upgrade hooks
@@ -390,6 +391,9 @@ func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *rele
}
if u.Wait {
+ u.cfg.Log(
+ "waiting for release %s resources (created: %d updated: %d deleted: %d)",
+ upgradedRelease.Name, len(results.Created), len(results.Updated), len(results.Deleted))
if u.WaitForJobs {
if err := u.cfg.KubeClient.WaitWithJobs(target, u.Timeout); err != nil {
u.cfg.recordRelease(originalRelease)
diff --git a/vendor/helm.sh/helm/v3/pkg/action/validate.go b/vendor/helm.sh/helm/v3/pkg/action/validate.go
index 6e074f78b..73eb1937b 100644
--- a/vendor/helm.sh/helm/v3/pkg/action/validate.go
+++ b/vendor/helm.sh/helm/v3/pkg/action/validate.go
@@ -51,7 +51,7 @@ func existingResourceConflict(resources kube.ResourceList, releaseName, releaseN
if apierrors.IsNotFound(err) {
return nil
}
- return errors.Wrap(err, "could not get information about the resource")
+ return errors.Wrapf(err, "could not get information about the resource %s", resourceString(info))
}
// Allow adoption of the resource if it is managed by Helm and is annotated with correct release name and namespace.
diff --git a/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go b/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go
index b49a31b01..f634d6425 100644
--- a/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go
+++ b/vendor/helm.sh/helm/v3/pkg/chartutil/coalesce.go
@@ -17,6 +17,7 @@ limitations under the License.
package chartutil
import (
+ "fmt"
"log"
"github.com/mitchellh/copystructure"
@@ -25,6 +26,13 @@ import (
"helm.sh/helm/v3/pkg/chart"
)
+func concatPrefix(a, b string) string {
+ if a == "" {
+ return b
+ }
+ return fmt.Sprintf("%s.%s", a, b)
+}
+
// CoalesceValues coalesces all of the values in a chart (and its subcharts).
//
// Values are coalesced together using the following rules:
@@ -45,19 +53,21 @@ func CoalesceValues(chrt *chart.Chart, vals map[string]interface{}) (Values, err
if valsCopy == nil {
valsCopy = make(map[string]interface{})
}
- return coalesce(chrt, valsCopy)
+ return coalesce(log.Printf, chrt, valsCopy, "")
}
+type printFn func(format string, v ...interface{})
+
// coalesce coalesces the dest values and the chart values, giving priority to the dest values.
//
// This is a helper function for CoalesceValues.
-func coalesce(ch *chart.Chart, dest map[string]interface{}) (map[string]interface{}, error) {
- coalesceValues(ch, dest)
- return coalesceDeps(ch, dest)
+func coalesce(printf printFn, ch *chart.Chart, dest map[string]interface{}, prefix string) (map[string]interface{}, error) {
+ coalesceValues(printf, ch, dest, prefix)
+ return coalesceDeps(printf, ch, dest, prefix)
}
// coalesceDeps coalesces the dependencies of the given chart.
-func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]interface{}, error) {
+func coalesceDeps(printf printFn, chrt *chart.Chart, dest map[string]interface{}, prefix string) (map[string]interface{}, error) {
for _, subchart := range chrt.Dependencies() {
if c, ok := dest[subchart.Name()]; !ok {
// If dest doesn't already have the key, create it.
@@ -67,13 +77,14 @@ func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]in
}
if dv, ok := dest[subchart.Name()]; ok {
dvmap := dv.(map[string]interface{})
+ subPrefix := concatPrefix(prefix, chrt.Metadata.Name)
// Get globals out of dest and merge them into dvmap.
- coalesceGlobals(dvmap, dest)
+ coalesceGlobals(printf, dvmap, dest, subPrefix)
// Now coalesce the rest of the values.
var err error
- dest[subchart.Name()], err = coalesce(subchart, dvmap)
+ dest[subchart.Name()], err = coalesce(printf, subchart, dvmap, subPrefix)
if err != nil {
return dest, err
}
@@ -85,20 +96,20 @@ func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]in
// coalesceGlobals copies the globals out of src and merges them into dest.
//
// For convenience, returns dest.
-func coalesceGlobals(dest, src map[string]interface{}) {
+func coalesceGlobals(printf printFn, dest, src map[string]interface{}, prefix string) {
var dg, sg map[string]interface{}
if destglob, ok := dest[GlobalKey]; !ok {
dg = make(map[string]interface{})
} else if dg, ok = destglob.(map[string]interface{}); !ok {
- log.Printf("warning: skipping globals because destination %s is not a table.", GlobalKey)
+ 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 {
- log.Printf("warning: skipping globals because source %s is not a table.", GlobalKey)
+ printf("warning: skipping globals because source %s is not a table.", GlobalKey)
return
}
@@ -114,17 +125,18 @@ func coalesceGlobals(dest, src map[string]interface{}) {
dg[key] = vv
} else {
if destvmap, ok := destv.(map[string]interface{}); !ok {
- log.Printf("Conflict: cannot merge map onto non-map for %q. Skipping.", key)
+ printf("Conflict: cannot merge map onto non-map for %q. Skipping.", key)
} else {
// Basically, we reverse order of coalesce here to merge
// top-down.
- CoalesceTables(vv, destvmap)
+ subPrefix := concatPrefix(prefix, key)
+ coalesceTablesFullKey(printf, vv, destvmap, subPrefix)
dg[key] = vv
}
}
} else if dv, ok := dg[key]; ok && istable(dv) {
// It's not clear if this condition can actually ever trigger.
- log.Printf("key %s is table. Skipping", key)
+ printf("key %s is table. Skipping", key)
} else {
// TODO: Do we need to do any additional checking on the value?
dg[key] = val
@@ -144,7 +156,8 @@ 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(c *chart.Chart, v map[string]interface{}) {
+func coalesceValues(printf printFn, c *chart.Chart, v map[string]interface{}, prefix string) {
+ subPrefix := concatPrefix(prefix, c.Metadata.Name)
for key, val := range c.Values {
if value, ok := v[key]; ok {
if value == nil {
@@ -159,12 +172,12 @@ func coalesceValues(c *chart.Chart, v map[string]interface{}) {
// If the original value is nil, there is nothing to coalesce, so we don't print
// the warning
if val != nil {
- log.Printf("warning: skipped value for %s: Not a table.", key)
+ printf("warning: skipped value for %s.%s: Not a table.", subPrefix, key)
}
} else {
// Because v has higher precedence than nv, dest values override src
// values.
- CoalesceTables(dest, src)
+ coalesceTablesFullKey(printf, dest, src, concatPrefix(subPrefix, key))
}
}
} else {
@@ -178,6 +191,13 @@ func coalesceValues(c *chart.Chart, v map[string]interface{}) {
//
// dest is considered authoritative.
func CoalesceTables(dst, src map[string]interface{}) map[string]interface{} {
+ 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{} {
// When --reuse-values is set but there are no modifications yet, return new values
if src == nil {
return dst
@@ -188,18 +208,19 @@ func CoalesceTables(dst, src map[string]interface{}) map[string]interface{} {
// Because dest has higher precedence than src, dest values override src
// values.
for key, val := range src {
+ fullkey := concatPrefix(prefix, key)
if dv, ok := dst[key]; ok && dv == nil {
delete(dst, key)
} else if !ok {
dst[key] = val
} else if istable(val) {
if istable(dv) {
- CoalesceTables(dv.(map[string]interface{}), val.(map[string]interface{}))
+ coalesceTablesFullKey(printf, dv.(map[string]interface{}), val.(map[string]interface{}), fullkey)
} else {
- log.Printf("warning: cannot overwrite table with non table for %s (%v)", key, val)
+ printf("warning: cannot overwrite table with non table for %s (%v)", fullkey, val)
}
} else if istable(dv) && val != nil {
- log.Printf("warning: destination for %s is a table. Ignoring non-table value %v", key, val)
+ printf("warning: destination for %s is a table. Ignoring non-table value (%v)", fullkey, val)
}
}
return dst
diff --git a/vendor/helm.sh/helm/v3/pkg/chartutil/dependencies.go b/vendor/helm.sh/helm/v3/pkg/chartutil/dependencies.go
index d2e7d6dc9..e01b95bf7 100644
--- a/vendor/helm.sh/helm/v3/pkg/chartutil/dependencies.go
+++ b/vendor/helm.sh/helm/v3/pkg/chartutil/dependencies.go
@@ -268,7 +268,7 @@ func processImportValues(c *chart.Chart) error {
}
// set the new values
- c.Values = CoalesceTables(b, cvals)
+ c.Values = CoalesceTables(cvals, b)
return nil
}
diff --git a/vendor/helm.sh/helm/v3/pkg/chartutil/validate_name.go b/vendor/helm.sh/helm/v3/pkg/chartutil/validate_name.go
index d253731ec..05c090cb6 100644
--- a/vendor/helm.sh/helm/v3/pkg/chartutil/validate_name.go
+++ b/vendor/helm.sh/helm/v3/pkg/chartutil/validate_name.go
@@ -40,19 +40,24 @@ var (
errMissingName = errors.New("no name provided")
// errInvalidName indicates that an invalid release name was provided
- errInvalidName = errors.New(fmt.Sprintf(
+ errInvalidName = fmt.Errorf(
"invalid release name, must match regex %s and the length must not be longer than 53",
- validName.String()))
+ validName.String())
// errInvalidKubernetesName indicates that the name does not meet the Kubernetes
// restrictions on metadata names.
- errInvalidKubernetesName = errors.New(fmt.Sprintf(
+ errInvalidKubernetesName = fmt.Errorf(
"invalid metadata name, must match regex %s and the length must not be longer than 253",
- validName.String()))
+ validName.String())
)
const (
- // maxNameLen is the maximum length Helm allows for a release name
+ // 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
diff --git a/vendor/helm.sh/helm/v3/pkg/cli/environment.go b/vendor/helm.sh/helm/v3/pkg/cli/environment.go
index ee60d981f..d5b208015 100644
--- a/vendor/helm.sh/helm/v3/pkg/cli/environment.go
+++ b/vendor/helm.sh/helm/v3/pkg/cli/environment.go
@@ -81,7 +81,7 @@ func New() *EnvSettings {
KubeAPIServer: os.Getenv("HELM_KUBEAPISERVER"),
KubeCaFile: os.Getenv("HELM_KUBECAFILE"),
PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")),
- RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry.json")),
+ RegistryConfig: envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry/config.json")),
RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")),
RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
}
@@ -180,6 +180,11 @@ func (s *EnvSettings) Namespace() string {
return "default"
}
+// SetNamespace sets the namespace in the configuration
+func (s *EnvSettings) SetNamespace(namespace string) {
+ s.namespace = namespace
+}
+
// RESTClientGetter gets the kubeconfig from EnvSettings
func (s *EnvSettings) RESTClientGetter() genericclioptions.RESTClientGetter {
return s.config
diff --git a/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go b/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go
index 93afb1461..3feb5b702 100644
--- a/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go
+++ b/vendor/helm.sh/helm/v3/pkg/downloader/chart_downloader.go
@@ -23,14 +23,15 @@ import (
"path/filepath"
"strings"
+ "github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/internal/fileutil"
"helm.sh/helm/v3/internal/urlutil"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/helmpath"
"helm.sh/helm/v3/pkg/provenance"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/repo"
)
@@ -103,7 +104,8 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
name := filepath.Base(u.Path)
if u.Scheme == registry.OCIScheme {
- name = fmt.Sprintf("%s-%s.tgz", name, version)
+ idx := strings.LastIndexByte(name, ':')
+ name = fmt.Sprintf("%s-%s.tgz", name[:idx], name[idx+1:])
}
destfile := filepath.Join(dest, name)
@@ -139,12 +141,46 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
return destfile, ver, nil
}
+func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, error) {
+ var tag string
+ var err error
+
+ // Evaluate whether an explicit version has been provided. Otherwise, determine version to use
+ _, errSemVer := semver.NewVersion(version)
+ if errSemVer == nil {
+ tag = version
+ } else {
+ // Retrieve list of repository tags
+ tags, err := c.RegistryClient.Tags(strings.TrimPrefix(ref, fmt.Sprintf("%s://", registry.OCIScheme)))
+ if err != nil {
+ return nil, err
+ }
+ if len(tags) == 0 {
+ return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref)
+ }
+
+ // Determine if version provided
+ // If empty, try to get the highest available tag
+ // If exact version, try to find it
+ // If semver constraint string, try to find a match
+ tag, err = registry.GetTagMatchingVersionOrConstraint(tags, version)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ u.Path = fmt.Sprintf("%s:%s", u.Path, tag)
+
+ return u, err
+}
+
// ResolveChartVersion resolves a chart reference to a URL.
//
// It returns the URL and sets the ChartDownloader's Options that can fetch
// the URL using the appropriate Getter.
//
-// A reference may be an HTTP URL, a 'reponame/chartname' reference, or a local path.
+// A reference may be an HTTP URL, an oci reference URL, a 'reponame/chartname'
+// reference, or a local path.
//
// A version is a SemVer string (1.2.3-beta.1+f334a6789).
//
@@ -159,6 +195,10 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er
return nil, errors.Errorf("invalid chart URL format: %s", ref)
}
+ if registry.IsOCI(u.String()) {
+ return c.getOciURI(ref, version, u)
+ }
+
rf, err := loadRepoConfig(c.RepositoryConfig)
if err != nil {
return u, err
diff --git a/vendor/helm.sh/helm/v3/pkg/downloader/manager.go b/vendor/helm.sh/helm/v3/pkg/downloader/manager.go
index b0ade6c90..18b28dde1 100644
--- a/vendor/helm.sh/helm/v3/pkg/downloader/manager.go
+++ b/vendor/helm.sh/helm/v3/pkg/downloader/manager.go
@@ -34,7 +34,6 @@ import (
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/internal/resolver"
"helm.sh/helm/v3/internal/third_party/dep/fs"
"helm.sh/helm/v3/internal/urlutil"
@@ -43,6 +42,7 @@ import (
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/helmpath"
+ "helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/repo"
)
@@ -232,7 +232,7 @@ func (m *Manager) loadChartDir() (*chart.Chart, error) {
//
// This returns a lock file, which has all of the dependencies normalized to a specific version.
func (m *Manager) resolve(req []*chart.Dependency, repoNames map[string]string) (*chart.Lock, error) {
- res := resolver.New(m.ChartPath, m.RepositoryCache)
+ res := resolver.New(m.ChartPath, m.RepositoryCache, m.RegistryClient)
return res.Resolve(req, repoNames)
}
@@ -332,6 +332,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
Keyring: m.Keyring,
RepositoryConfig: m.RepositoryConfig,
RepositoryCache: m.RepositoryCache,
+ RegistryClient: m.RegistryClient,
Getters: m.Getters,
Options: []getter.Option{
getter.WithBasicAuth(username, password),
@@ -342,12 +343,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
}
version := ""
- if strings.HasPrefix(churl, "oci://") {
- if !resolver.FeatureGateOCI.IsEnabled() {
- return errors.Wrapf(resolver.FeatureGateOCI.Error(),
- "the repository %s is an OCI registry", churl)
- }
-
+ if registry.IsOCI(churl) {
churl, version, err = parseOCIRef(churl)
if err != nil {
return errors.Wrapf(err, "could not parse OCI reference")
@@ -404,12 +400,12 @@ func parseOCIRef(chartRef string) (string, string, error) {
func (m *Manager) safeMoveDeps(deps []*chart.Dependency, source, dest string) error {
existsInSourceDirectory := map[string]bool{}
isLocalDependency := map[string]bool{}
- sourceFiles, err := ioutil.ReadDir(source)
+ sourceFiles, err := os.ReadDir(source)
if err != nil {
return err
}
// attempt to read destFiles; fail fast if we can't
- destFiles, err := ioutil.ReadDir(dest)
+ destFiles, err := os.ReadDir(dest)
if err != nil {
return err
}
@@ -440,7 +436,7 @@ func (m *Manager) safeMoveDeps(deps []*chart.Dependency, source, dest string) er
}
fmt.Fprintln(m.Out, "Deleting outdated charts")
- // find all files that exist in dest that do not exist in source; delete them (outdated dependendencies)
+ // find all files that exist in dest that do not exist in source; delete them (outdated dependencies)
for _, file := range destFiles {
if !file.IsDir() && !existsInSourceDirectory[file.Name()] {
fname := filepath.Join(dest, file.Name())
@@ -477,7 +473,7 @@ func (m *Manager) hasAllRepos(deps []*chart.Dependency) error {
Loop:
for _, dd := range deps {
// If repo is from local path or OCI, continue
- if strings.HasPrefix(dd.Repository, "file://") || strings.HasPrefix(dd.Repository, "oci://") {
+ if strings.HasPrefix(dd.Repository, "file://") || registry.IsOCI(dd.Repository) {
continue
}
@@ -578,8 +574,7 @@ func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string,
missing := []string{}
for _, dd := range deps {
// Don't map the repository, we don't need to download chart from charts directory
- // When OCI is used there is no Helm repository
- if dd.Repository == "" || strings.HasPrefix(dd.Repository, "oci://") {
+ if dd.Repository == "" {
continue
}
// if dep chart is from local path, verify the path is valid
@@ -595,7 +590,7 @@ func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string,
continue
}
- if strings.HasPrefix(dd.Repository, "oci://") {
+ if registry.IsOCI(dd.Repository) {
reposMap[dd.Name] = dd.Repository
continue
}
@@ -709,7 +704,7 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error {
//
// If it finds a URL that is "relative", it will prepend the repoURL.
func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password string, insecureskiptlsverify, passcredentialsall bool, caFile, certFile, keyFile string, err error) {
- if strings.HasPrefix(repoURL, "oci://") {
+ if registry.IsOCI(repoURL) {
return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", false, false, "", "", "", nil
}
diff --git a/vendor/helm.sh/helm/v3/pkg/getter/getter.go b/vendor/helm.sh/helm/v3/pkg/getter/getter.go
index 3a0567a87..653b032fe 100644
--- a/vendor/helm.sh/helm/v3/pkg/getter/getter.go
+++ b/vendor/helm.sh/helm/v3/pkg/getter/getter.go
@@ -18,12 +18,13 @@ package getter
import (
"bytes"
+ "net/http"
"time"
"github.com/pkg/errors"
- "helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/cli"
+ "helm.sh/helm/v3/pkg/registry"
)
// options are generic parameters to be provided to the getter during instantiation.
@@ -43,6 +44,7 @@ type options struct {
version string
registryClient *registry.Client
timeout time.Duration
+ transport *http.Transport
}
// Option allows specifying various settings configurable by the user for overriding the defaults
@@ -119,6 +121,13 @@ func WithUntar() Option {
}
}
+// WithTransport sets the http.Transport to allow overwriting the HTTPGetter default.
+func WithTransport(transport *http.Transport) Option {
+ return func(opts *options) {
+ opts.transport = transport
+ }
+}
+
// Getter is an interface to support GET to the specified URL.
type Getter interface {
// Get file content by url string
diff --git a/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go b/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go
index 454eb6eb6..6fe1aa71f 100644
--- a/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go
+++ b/vendor/helm.sh/helm/v3/pkg/getter/httpgetter.go
@@ -21,6 +21,7 @@ import (
"io"
"net/http"
"net/url"
+ "sync"
"github.com/pkg/errors"
@@ -31,7 +32,9 @@ import (
// HTTPGetter is the default HTTP(/S) backend handler
type HTTPGetter struct {
- opts options
+ opts options
+ transport *http.Transport
+ once sync.Once
}
// Get performs a Get from repo.Getter and returns the body.
@@ -106,10 +109,20 @@ func NewHTTPGetter(options ...Option) (Getter, error) {
}
func (g *HTTPGetter) httpClient() (*http.Client, error) {
- transport := &http.Transport{
- DisableCompression: true,
- Proxy: http.ProxyFromEnvironment,
+ if g.opts.transport != nil {
+ return &http.Client{
+ Transport: g.opts.transport,
+ Timeout: g.opts.timeout,
+ }, nil
}
+
+ g.once.Do(func() {
+ g.transport = &http.Transport{
+ DisableCompression: true,
+ Proxy: http.ProxyFromEnvironment,
+ }
+ })
+
if (g.opts.certFile != "" && g.opts.keyFile != "") || g.opts.caFile != "" {
tlsConf, err := tlsutil.NewClientTLS(g.opts.certFile, g.opts.keyFile, g.opts.caFile)
if err != nil {
@@ -123,21 +136,21 @@ func (g *HTTPGetter) httpClient() (*http.Client, error) {
}
tlsConf.ServerName = sni
- transport.TLSClientConfig = tlsConf
+ g.transport.TLSClientConfig = tlsConf
}
if g.opts.insecureSkipVerifyTLS {
- if transport.TLSClientConfig == nil {
- transport.TLSClientConfig = &tls.Config{
+ if g.transport.TLSClientConfig == nil {
+ g.transport.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
} else {
- transport.TLSClientConfig.InsecureSkipVerify = true
+ g.transport.TLSClientConfig.InsecureSkipVerify = true
}
}
client := &http.Client{
- Transport: transport,
+ Transport: g.transport,
Timeout: g.opts.timeout,
}
diff --git a/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go b/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go
index 45c92749c..14f5cb3ec 100644
--- a/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go
+++ b/vendor/helm.sh/helm/v3/pkg/getter/ocigetter.go
@@ -20,7 +20,7 @@ import (
"fmt"
"strings"
- "helm.sh/helm/v3/internal/experimental/registry"
+ "helm.sh/helm/v3/pkg/registry"
)
// OCIGetter is the default HTTP(/S) backend handler
@@ -28,7 +28,7 @@ type OCIGetter struct {
opts options
}
-//Get performs a Get from repo.Getter and returns the body.
+// Get performs a Get from repo.Getter and returns the body.
func (g *OCIGetter) Get(href string, options ...Option) (*bytes.Buffer, error) {
for _, opt := range options {
opt(&g.opts)
@@ -50,10 +50,6 @@ func (g *OCIGetter) get(href string) (*bytes.Buffer, error) {
registry.PullOptWithProv(true))
}
- if version := g.opts.version; version != "" {
- ref = fmt.Sprintf("%s:%s", ref, version)
- }
-
result, err := client.Pull(ref, pullOpts...)
if err != nil {
return nil, err
@@ -67,7 +63,9 @@ func (g *OCIGetter) get(href string) (*bytes.Buffer, error) {
// NewOCIGetter constructs a valid http/https client as a Getter
func NewOCIGetter(ops ...Option) (Getter, error) {
- registryClient, err := registry.NewClient()
+ registryClient, err := registry.NewClient(
+ registry.ClientOptEnableCache(true),
+ )
if err != nil {
return nil, err
}
diff --git a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_darwin.go b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_darwin.go
index 80477abab..eba6dde15 100644
--- a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_darwin.go
+++ b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_darwin.go
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build darwin
-// +build darwin
package helmpath
diff --git a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_unix.go b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_unix.go
index a5afc1237..82fb4b6f1 100644
--- a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_unix.go
+++ b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_unix.go
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build !windows && !darwin
-// +build !windows,!darwin
package helmpath
diff --git a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_windows.go b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_windows.go
index 057a3af14..230aee2a9 100644
--- a/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_windows.go
+++ b/vendor/helm.sh/helm/v3/pkg/helmpath/lazypath_windows.go
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// +build windows
+//go:build windows
package helmpath
diff --git a/vendor/helm.sh/helm/v3/pkg/kube/client.go b/vendor/helm.sh/helm/v3/pkg/kube/client.go
index cc38243ac..38c8b93f2 100644
--- a/vendor/helm.sh/helm/v3/pkg/kube/client.go
+++ b/vendor/helm.sh/helm/v3/pkg/kube/client.go
@@ -192,7 +192,18 @@ func (c *Client) newBuilder() *resource.Builder {
// Build validates for Kubernetes objects and returns unstructured infos.
func (c *Client) Build(reader io.Reader, validate bool) (ResourceList, error) {
- schema, err := c.Factory.Validator(validate)
+ validationDirective := metav1.FieldValidationIgnore
+ if validate {
+ validationDirective = metav1.FieldValidationStrict
+ }
+
+ dynamicClient, err := c.Factory.DynamicClient()
+ if err != nil {
+ return nil, err
+ }
+
+ verifier := resource.NewQueryParamVerifier(dynamicClient, c.Factory.OpenAPIGetter(), resource.QueryParamFieldValidation)
+ schema, err := c.Factory.Validator(validationDirective, verifier)
if err != nil {
return nil, err
}
@@ -264,7 +275,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err
}
for _, info := range original.Difference(target) {
- c.Log("Deleting %q in %s...", info.Name, info.Namespace)
+ c.Log("Deleting %s %q in namespace %s...", info.Mapping.GroupVersionKind.Kind, info.Name, info.Namespace)
if err := info.Get(); err != nil {
c.Log("Unable to get obj %q, err: %s", info.Name, err)
@@ -498,7 +509,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
}
if patch == nil || string(patch) == "{}" {
- c.Log("Looks like there are no changes for %s %q", target.Mapping.GroupVersionKind.Kind, target.Name)
+ c.Log("Looks like there are no changes for %s %q", kind, target.Name)
// This needs to happen to make sure that Helm has the latest info from the API
// Otherwise there will be no labels and other functions that use labels will panic
if err := target.Get(); err != nil {
@@ -507,6 +518,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
return nil
}
// send patch to server
+ c.Log("Patch %s %q in namespace %s", kind, target.Name, target.Namespace)
obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil)
if err != nil {
return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind)
@@ -645,6 +657,9 @@ func (c *Client) WaitAndGetCompletedPodPhase(name string, timeout time.Duration)
FieldSelector: fmt.Sprintf("metadata.name=%s", name),
TimeoutSeconds: &to,
})
+ if err != nil {
+ return v1.PodUnknown, err
+ }
for event := range watcher.ResultChan() {
p, ok := event.Object.(*v1.Pod)
diff --git a/vendor/helm.sh/helm/v3/pkg/kube/factory.go b/vendor/helm.sh/helm/v3/pkg/kube/factory.go
index f47f9d9f6..fdba8cf8f 100644
--- a/vendor/helm.sh/helm/v3/pkg/kube/factory.go
+++ b/vendor/helm.sh/helm/v3/pkg/kube/factory.go
@@ -18,6 +18,8 @@ package kube // import "helm.sh/helm/v3/pkg/kube"
import (
"k8s.io/cli-runtime/pkg/resource"
+ "k8s.io/client-go/discovery"
+ "k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubectl/pkg/validation"
@@ -28,11 +30,19 @@ import (
type Factory interface {
// ToRawKubeConfigLoader return kubeconfig loader as-is
ToRawKubeConfigLoader() clientcmd.ClientConfig
+
+ // DynamicClient returns a dynamic client ready for use
+ DynamicClient() (dynamic.Interface, error)
+
// KubernetesClientSet gives you back an external clientset
KubernetesClientSet() (*kubernetes.Clientset, error)
+
// NewBuilder returns an object that assists in loading objects from both disk and the server
// and which implements the common patterns for CLI interactions with generic resources.
NewBuilder() *resource.Builder
+
// Returns a schema that can validate objects stored on disk.
- Validator(validate bool) (validation.Schema, error)
+ Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error)
+ // OpenAPIGetter returns a getter for the openapi schema document
+ OpenAPIGetter() discovery.OpenAPISchemaInterface
}
diff --git a/vendor/helm.sh/helm/v3/pkg/kube/ready.go b/vendor/helm.sh/helm/v3/pkg/kube/ready.go
index 106c0be51..0554c1729 100644
--- a/vendor/helm.sh/helm/v3/pkg/kube/ready.go
+++ b/vendor/helm.sh/helm/v3/pkg/kube/ready.go
@@ -353,9 +353,16 @@ func (c *ReadyChecker) crdReady(crd apiextv1.CustomResourceDefinition) bool {
func (c *ReadyChecker) statefulSetReady(sts *appsv1.StatefulSet) bool {
// If the update strategy is not a rolling update, there will be nothing to wait for
if sts.Spec.UpdateStrategy.Type != appsv1.RollingUpdateStatefulSetStrategyType {
+ c.log("StatefulSet skipped ready check: %s/%s. updateStrategy is %v", sts.Namespace, sts.Name, sts.Spec.UpdateStrategy.Type)
return true
}
+ // Make sure the status is up-to-date with the StatefulSet changes
+ if sts.Status.ObservedGeneration < sts.Generation {
+ c.log("StatefulSet is not ready: %s/%s. update has not yet been observed", sts.Namespace, sts.Name)
+ return false
+ }
+
// Dereference all the pointers because StatefulSets like them
var partition int
// 1 is the default for replicas if not set
@@ -377,7 +384,7 @@ func (c *ReadyChecker) statefulSetReady(sts *appsv1.StatefulSet) bool {
expectedReplicas := replicas - partition
// Make sure all the updated pods have been scheduled
- if int(sts.Status.UpdatedReplicas) != expectedReplicas {
+ if int(sts.Status.UpdatedReplicas) < expectedReplicas {
c.log("StatefulSet is not ready: %s/%s. %d out of %d expected pods have been scheduled", sts.Namespace, sts.Name, sts.Status.UpdatedReplicas, expectedReplicas)
return false
}
@@ -386,6 +393,13 @@ func (c *ReadyChecker) statefulSetReady(sts *appsv1.StatefulSet) bool {
c.log("StatefulSet is not ready: %s/%s. %d out of %d expected pods are ready", sts.Namespace, sts.Name, sts.Status.ReadyReplicas, replicas)
return false
}
+
+ if sts.Status.CurrentRevision != sts.Status.UpdateRevision {
+ c.log("StatefulSet is not ready: %s/%s. currentRevision %s does not yet match updateRevision %s", sts.Namespace, sts.Name, sts.Status.CurrentRevision, sts.Status.UpdateRevision)
+ return false
+ }
+
+ c.log("StatefulSet is ready: %s/%s. %d out of %d expected pods are ready", sts.Namespace, sts.Name, sts.Status.ReadyReplicas, replicas)
return true
}
diff --git a/vendor/helm.sh/helm/v3/pkg/lint/rules/template.go b/vendor/helm.sh/helm/v3/pkg/lint/rules/template.go
index b4bfe33e2..61425f92e 100644
--- a/vendor/helm.sh/helm/v3/pkg/lint/rules/template.go
+++ b/vendor/helm.sh/helm/v3/pkg/lint/rules/template.go
@@ -70,6 +70,12 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
Namespace: namespace,
}
+ // lint ignores import-values
+ // See https://github.com/helm/helm/issues/9658
+ if err := chartutil.ProcessDependencies(chart, values); err != nil {
+ return
+ }
+
cvals, err := chartutil.CoalesceValues(chart, values)
if err != nil {
return
diff --git a/vendor/helm.sh/helm/v3/pkg/postrender/exec.go b/vendor/helm.sh/helm/v3/pkg/postrender/exec.go
index 1de70b024..167e737d6 100644
--- a/vendor/helm.sh/helm/v3/pkg/postrender/exec.go
+++ b/vendor/helm.sh/helm/v3/pkg/postrender/exec.go
@@ -27,23 +27,24 @@ import (
type execRender struct {
binaryPath string
+ args []string
}
// NewExec returns a PostRenderer implementation that calls the provided binary.
// It returns an error if the binary cannot be found. If the path does not
// contain any separators, it will search in $PATH, otherwise it will resolve
// any relative paths to a fully qualified path
-func NewExec(binaryPath string) (PostRenderer, error) {
+func NewExec(binaryPath string, args ...string) (PostRenderer, error) {
fullPath, err := getFullPath(binaryPath)
if err != nil {
return nil, err
}
- return &execRender{fullPath}, nil
+ return &execRender{fullPath, args}, nil
}
// Run the configured binary for the post render
func (p *execRender) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) {
- cmd := exec.Command(p.binaryPath)
+ cmd := exec.Command(p.binaryPath, p.args...)
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
diff --git a/vendor/helm.sh/helm/v3/pkg/provenance/sign.go b/vendor/helm.sh/helm/v3/pkg/provenance/sign.go
index 5d16779f1..c41f90c61 100644
--- a/vendor/helm.sh/helm/v3/pkg/provenance/sign.go
+++ b/vendor/helm.sh/helm/v3/pkg/provenance/sign.go
@@ -26,9 +26,9 @@ import (
"strings"
"github.com/pkg/errors"
- "golang.org/x/crypto/openpgp"
- "golang.org/x/crypto/openpgp/clearsign"
- "golang.org/x/crypto/openpgp/packet"
+ "golang.org/x/crypto/openpgp" //nolint
+ "golang.org/x/crypto/openpgp/clearsign" //nolint
+ "golang.org/x/crypto/openpgp/packet" //nolint
"sigs.k8s.io/yaml"
hapi "helm.sh/helm/v3/pkg/chart"
@@ -216,7 +216,7 @@ func (s *Signatory) ClearSign(chartpath string) (string, error) {
b, err := messageBlock(chartpath)
if err != nil {
- return "", nil
+ return "", err
}
// Sign the buffer
@@ -224,9 +224,24 @@ func (s *Signatory) ClearSign(chartpath string) (string, error) {
if err != nil {
return "", err
}
+
_, err = io.Copy(w, b)
- w.Close()
- return out.String(), err
+
+ if err != nil {
+ // NB: We intentionally don't call `w.Close()` here! `w.Close()` is the method which
+ // actually does the PGP signing, and therefore is the part which uses the private key.
+ // In other words, if we call Close here, there's a risk that there's an attempt to use the
+ // private key to sign garbage data (since we know that io.Copy failed, `w` won't contain
+ // anything useful).
+ return "", errors.Wrap(err, "failed to write to clearsign encoder")
+ }
+
+ err = w.Close()
+ if err != nil {
+ return "", errors.Wrap(err, "failed to either sign or armor message block")
+ }
+
+ return out.String(), nil
}
// Verify checks a signature and verifies that it is legit for a chart.
diff --git a/vendor/helm.sh/helm/v3/pkg/gates/gates.go b/vendor/helm.sh/helm/v3/pkg/pusher/doc.go
index 69559219e..df89ab112 100644
--- a/vendor/helm.sh/helm/v3/pkg/gates/gates.go
+++ b/vendor/helm.sh/helm/v3/pkg/pusher/doc.go
@@ -13,26 +13,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package gates
-
-import (
- "fmt"
- "os"
-)
-
-// Gate is the name of the feature gate.
-type Gate string
-
-// String returns the string representation of this feature gate.
-func (g Gate) String() string {
- return string(g)
-}
-
-// IsEnabled determines whether a certain feature gate is enabled.
-func (g Gate) IsEnabled() bool {
- return os.Getenv(string(g)) != ""
-}
-
-func (g Gate) Error() error {
- return fmt.Errorf("this feature has been marked as experimental and is not enabled by default. Please set %s=1 in your environment to use this feature", g.String())
-}
+/*
+Package pusher provides a generalized tool for uploading data by scheme.
+This provides a method by which the plugin system can load arbitrary protocol
+handlers based upon a URL scheme.
+*/
+package pusher
diff --git a/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go b/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go
new file mode 100644
index 000000000..7c90e85a4
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/pusher/ocipusher.go
@@ -0,0 +1,106 @@
+/*
+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 pusher
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ "helm.sh/helm/v3/pkg/chart/loader"
+ "helm.sh/helm/v3/pkg/registry"
+)
+
+// OCIPusher is the default OCI backend handler
+type OCIPusher struct {
+ opts options
+}
+
+// Push performs a Push from repo.Pusher.
+func (pusher *OCIPusher) Push(chartRef, href string, options ...Option) error {
+ for _, opt := range options {
+ opt(&pusher.opts)
+ }
+ return pusher.push(chartRef, href)
+}
+
+func (pusher *OCIPusher) push(chartRef, href string) error {
+ stat, err := os.Stat(chartRef)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return errors.Errorf("%s: no such file", chartRef)
+ }
+ return err
+ }
+ if stat.IsDir() {
+ return errors.New("cannot push directory, must provide chart archive (.tgz)")
+ }
+
+ meta, err := loader.Load(chartRef)
+ if err != nil {
+ return err
+ }
+
+ client := pusher.opts.registryClient
+
+ chartBytes, err := ioutil.ReadFile(chartRef)
+ if err != nil {
+ return err
+ }
+
+ var pushOpts []registry.PushOption
+ provRef := fmt.Sprintf("%s.prov", chartRef)
+ if _, err := os.Stat(provRef); err == nil {
+ provBytes, err := ioutil.ReadFile(provRef)
+ if err != nil {
+ return err
+ }
+ pushOpts = append(pushOpts, registry.PushOptProvData(provBytes))
+ }
+
+ ref := fmt.Sprintf("%s:%s",
+ path.Join(strings.TrimPrefix(href, fmt.Sprintf("%s://", registry.OCIScheme)), meta.Metadata.Name),
+ meta.Metadata.Version)
+
+ _, err = client.Push(chartBytes, ref, pushOpts...)
+ return err
+}
+
+// NewOCIPusher constructs a valid OCI client as a Pusher
+func NewOCIPusher(ops ...Option) (Pusher, error) {
+ registryClient, err := registry.NewClient(
+ registry.ClientOptEnableCache(true),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ client := OCIPusher{
+ opts: options{
+ registryClient: registryClient,
+ },
+ }
+
+ for _, opt := range ops {
+ opt(&client.opts)
+ }
+
+ return &client, nil
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/pusher/pusher.go b/vendor/helm.sh/helm/v3/pkg/pusher/pusher.go
new file mode 100644
index 000000000..30c6af97c
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/pusher/pusher.go
@@ -0,0 +1,95 @@
+/*
+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 pusher
+
+import (
+ "github.com/pkg/errors"
+
+ "helm.sh/helm/v3/pkg/cli"
+ "helm.sh/helm/v3/pkg/registry"
+)
+
+// options are generic parameters to be provided to the pusher during instantiation.
+//
+// Pushers may or may not ignore these parameters as they are passed in.
+type options struct {
+ registryClient *registry.Client
+}
+
+// Option allows specifying various settings configurable by the user for overriding the defaults
+// used when performing Push operations with the Pusher.
+type Option func(*options)
+
+// WithRegistryClient sets the registryClient option.
+func WithRegistryClient(client *registry.Client) Option {
+ return func(opts *options) {
+ opts.registryClient = client
+ }
+}
+
+// Pusher is an interface to support upload to the specified URL.
+type Pusher interface {
+ // Push file content by url string
+ Push(chartRef, url string, options ...Option) error
+}
+
+// Constructor is the function for every pusher which creates a specific instance
+// according to the configuration
+type Constructor func(options ...Option) (Pusher, error)
+
+// Provider represents any pusher and the schemes that it supports.
+type Provider struct {
+ Schemes []string
+ New Constructor
+}
+
+// Provides returns true if the given scheme is supported by this Provider.
+func (p Provider) Provides(scheme string) bool {
+ for _, i := range p.Schemes {
+ if i == scheme {
+ return true
+ }
+ }
+ return false
+}
+
+// Providers is a collection of Provider objects.
+type Providers []Provider
+
+// ByScheme returns a Provider that handles the given scheme.
+//
+// If no provider handles this scheme, this will return an error.
+func (p Providers) ByScheme(scheme string) (Pusher, error) {
+ for _, pp := range p {
+ if pp.Provides(scheme) {
+ return pp.New()
+ }
+ }
+ return nil, errors.Errorf("scheme %q not supported", scheme)
+}
+
+var ociProvider = Provider{
+ Schemes: []string{registry.OCIScheme},
+ New: NewOCIPusher,
+}
+
+// All finds all of the registered pushers as a list of Provider instances.
+// Currently, just the built-in pushers are collected.
+func All(settings *cli.EnvSettings) Providers {
+ result := Providers{ociProvider}
+ return result
+}
diff --git a/vendor/helm.sh/helm/v3/internal/experimental/registry/client.go b/vendor/helm.sh/helm/v3/pkg/registry/client.go
index cc9e1fe79..c1004f956 100644
--- a/vendor/helm.sh/helm/v3/internal/experimental/registry/client.go
+++ b/vendor/helm.sh/helm/v3/pkg/registry/client.go
@@ -14,16 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package registry // import "helm.sh/helm/v3/internal/experimental/registry"
+package registry // import "helm.sh/helm/v3/pkg/registry"
import (
+ "context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
+ "sort"
"strings"
+ "github.com/Masterminds/semver/v3"
"github.com/containerd/containerd/remotes"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -31,21 +34,33 @@ import (
dockerauth "oras.land/oras-go/pkg/auth/docker"
"oras.land/oras-go/pkg/content"
"oras.land/oras-go/pkg/oras"
+ "oras.land/oras-go/pkg/registry"
+ registryremote "oras.land/oras-go/pkg/registry/remote"
+ registryauth "oras.land/oras-go/pkg/registry/remote/auth"
"helm.sh/helm/v3/internal/version"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/helmpath"
)
+// See https://github.com/helm/helm/issues/10166
+const registryUnderscoreMessage = `
+OCI artifact references (e.g. tags) do not support the plus sign (+). To support
+storing semantic versions, Helm adopts the convention of changing plus (+) to
+an underscore (_) in chart version tags when pushing to a registry and back to
+a plus (+) when pulling from a registry.`
+
type (
// Client works with OCI-compliant registries
Client struct {
- debug bool
+ debug bool
+ enableCache bool
// path to repository config file e.g. ~/.docker/config.json
- credentialsFile string
- out io.Writer
- authorizer auth.Client
- resolver remotes.Resolver
+ credentialsFile string
+ out io.Writer
+ authorizer auth.Client
+ registryAuthorizer *registryauth.Client
+ resolver remotes.Resolver
}
// ClientOption allows specifying various settings configurable by the user for overriding the defaults
@@ -65,7 +80,7 @@ func NewClient(options ...ClientOption) (*Client, error) {
client.credentialsFile = helmpath.ConfigPath(CredentialsFileBasename)
}
if client.authorizer == nil {
- authClient, err := dockerauth.NewClient(client.credentialsFile)
+ authClient, err := dockerauth.NewClientWithDockerFallback(client.credentialsFile)
if err != nil {
return nil, err
}
@@ -81,6 +96,45 @@ func NewClient(options ...ClientOption) (*Client, error) {
}
client.resolver = resolver
}
+
+ // allocate a cache if option is set
+ var cache registryauth.Cache
+ if client.enableCache {
+ cache = registryauth.DefaultCache
+ }
+ if client.registryAuthorizer == nil {
+ client.registryAuthorizer = &registryauth.Client{
+ Header: http.Header{
+ "User-Agent": {version.GetUserAgent()},
+ },
+ Cache: cache,
+ Credential: func(ctx context.Context, reg string) (registryauth.Credential, error) {
+ dockerClient, ok := client.authorizer.(*dockerauth.Client)
+ if !ok {
+ return registryauth.EmptyCredential, errors.New("unable to obtain docker client")
+ }
+
+ username, password, err := dockerClient.Credential(reg)
+ if err != nil {
+ return registryauth.EmptyCredential, errors.New("unable to retrieve credentials")
+ }
+
+ // A blank returned username and password value is a bearer token
+ if username == "" && password != "" {
+ return registryauth.Credential{
+ RefreshToken: password,
+ }, nil
+ }
+
+ return registryauth.Credential{
+ Username: username,
+ Password: password,
+ }, nil
+
+ },
+ }
+
+ }
return client, nil
}
@@ -91,6 +145,13 @@ func ClientOptDebug(debug bool) ClientOption {
}
}
+// ClientOptEnableCache returns a function that sets the enableCache setting on a client options set
+func ClientOptEnableCache(enableCache bool) ClientOption {
+ return func(client *Client) {
+ client.enableCache = enableCache
+ }
+}
+
// ClientOptWriter returns a function that sets the writer setting on client options set
func ClientOptWriter(out io.Writer) ClientOption {
return func(client *Client) {
@@ -207,6 +268,11 @@ type (
// Pull downloads a chart from a registry
func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
+ parsedRef, err := parseReference(ref)
+ if err != nil {
+ return nil, err
+ }
+
operation := &pullOperation{
withChart: true, // By default, always download the chart layer
}
@@ -217,7 +283,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
return nil, errors.New(
"must specify at least one layer to pull (chart/prov)")
}
- store := content.NewMemoryStore()
+ memoryStore := content.NewMemory()
allowedMediaTypes := []string{
ConfigMediaType,
}
@@ -232,17 +298,27 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
}
allowedMediaTypes = append(allowedMediaTypes, ProvLayerMediaType)
}
- manifest, descriptors, err := oras.Pull(ctx(c.out, c.debug), c.resolver, ref, store,
+
+ var descriptors, layers []ocispec.Descriptor
+ registryStore := content.Registry{Resolver: c.resolver}
+
+ manifest, err := oras.Copy(ctx(c.out, c.debug), registryStore, parsedRef.String(), memoryStore, "",
oras.WithPullEmptyNameAllowed(),
- oras.WithAllowedMediaTypes(allowedMediaTypes))
+ oras.WithAllowedMediaTypes(allowedMediaTypes),
+ oras.WithLayerDescriptors(func(l []ocispec.Descriptor) {
+ layers = l
+ }))
if err != nil {
return nil, err
}
+
+ descriptors = append(descriptors, manifest)
+ descriptors = append(descriptors, layers...)
+
numDescriptors := len(descriptors)
if numDescriptors < minNumDescriptors {
- return nil, errors.New(
- fmt.Sprintf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
- minNumDescriptors, numDescriptors))
+ return nil, fmt.Errorf("manifest does not contain minimum number of descriptors (%d), descriptors found: %d",
+ minNumDescriptors, numDescriptors)
}
var configDescriptor *ocispec.Descriptor
var chartDescriptor *ocispec.Descriptor
@@ -262,22 +338,19 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
}
}
if configDescriptor == nil {
- return nil, errors.New(
- fmt.Sprintf("could not load config with mediatype %s", ConfigMediaType))
+ return nil, fmt.Errorf("could not load config with mediatype %s", ConfigMediaType)
}
if operation.withChart && chartDescriptor == nil {
- return nil, errors.New(
- fmt.Sprintf("manifest does not contain a layer with mediatype %s",
- ChartLayerMediaType))
+ return nil, fmt.Errorf("manifest does not contain a layer with mediatype %s",
+ ChartLayerMediaType)
}
var provMissing bool
if operation.withProv && provDescriptor == nil {
if operation.ignoreMissingProv {
provMissing = true
} else {
- return nil, errors.New(
- fmt.Sprintf("manifest does not contain a layer with mediatype %s",
- ProvLayerMediaType))
+ return nil, fmt.Errorf("manifest does not contain a layer with mediatype %s",
+ ProvLayerMediaType)
}
}
result := &PullResult{
@@ -291,10 +364,10 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
},
Chart: &descriptorPullSummaryWithMeta{},
Prov: &descriptorPullSummary{},
- Ref: ref,
+ Ref: parsedRef.String(),
}
var getManifestErr error
- if _, manifestData, ok := store.Get(manifest); !ok {
+ if _, manifestData, ok := memoryStore.Get(manifest); !ok {
getManifestErr = errors.Errorf("Unable to retrieve blob with digest %s", manifest.Digest)
} else {
result.Manifest.Data = manifestData
@@ -303,7 +376,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
return nil, getManifestErr
}
var getConfigDescriptorErr error
- if _, configData, ok := store.Get(*configDescriptor); !ok {
+ if _, configData, ok := memoryStore.Get(*configDescriptor); !ok {
getConfigDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", configDescriptor.Digest)
} else {
result.Config.Data = configData
@@ -318,7 +391,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
}
if operation.withChart {
var getChartDescriptorErr error
- if _, chartData, ok := store.Get(*chartDescriptor); !ok {
+ if _, chartData, ok := memoryStore.Get(*chartDescriptor); !ok {
getChartDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", chartDescriptor.Digest)
} else {
result.Chart.Data = chartData
@@ -331,7 +404,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
}
if operation.withProv && !provMissing {
var getProvDescriptorErr error
- if _, provData, ok := store.Get(*provDescriptor); !ok {
+ if _, provData, ok := memoryStore.Get(*provDescriptor); !ok {
getProvDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", provDescriptor.Digest)
} else {
result.Prov.Data = provData
@@ -342,8 +415,15 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
return nil, getProvDescriptorErr
}
}
+
fmt.Fprintf(c.out, "Pulled: %s\n", result.Ref)
fmt.Fprintf(c.out, "Digest: %s\n", result.Manifest.Digest)
+
+ if strings.Contains(result.Ref, "_") {
+ fmt.Fprintf(c.out, "%s contains an underscore.\n", result.Ref)
+ fmt.Fprint(c.out, registryUnderscoreMessage+"\n")
+ }
+
return result, nil
}
@@ -399,6 +479,11 @@ type (
// Push uploads a chart to a registry.
func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResult, error) {
+ parsedRef, err := parseReference(ref)
+ if err != nil {
+ return nil, err
+ }
+
operation := &pushOperation{
strictMode: true, // By default, enable strict mode
}
@@ -415,21 +500,45 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
"strict mode enabled, ref basename and tag must match the chart name and version")
}
}
- store := content.NewMemoryStore()
- chartDescriptor := store.Add("", ChartLayerMediaType, data)
+ memoryStore := content.NewMemory()
+ chartDescriptor, err := memoryStore.Add("", ChartLayerMediaType, data)
+ if err != nil {
+ return nil, err
+ }
+
configData, err := json.Marshal(meta)
if err != nil {
return nil, err
}
- configDescriptor := store.Add("", ConfigMediaType, configData)
+
+ configDescriptor, err := memoryStore.Add("", ConfigMediaType, configData)
+ if err != nil {
+ return nil, err
+ }
+
descriptors := []ocispec.Descriptor{chartDescriptor}
var provDescriptor ocispec.Descriptor
if operation.provData != nil {
- provDescriptor = store.Add("", ProvLayerMediaType, operation.provData)
+ provDescriptor, err = memoryStore.Add("", ProvLayerMediaType, operation.provData)
+ if err != nil {
+ return nil, err
+ }
+
descriptors = append(descriptors, provDescriptor)
}
- manifest, err := oras.Push(ctx(c.out, c.debug), c.resolver, ref, store, descriptors,
- oras.WithConfig(configDescriptor), oras.WithNameValidation(nil))
+
+ manifestData, manifest, err := content.GenerateManifest(&configDescriptor, nil, descriptors...)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := memoryStore.StoreManifest(parsedRef.String(), manifest, manifestData); err != nil {
+ return nil, err
+ }
+
+ registryStore := content.Registry{Resolver: c.resolver}
+ _, err = oras.Copy(ctx(c.out, c.debug), memoryStore, parsedRef.String(), registryStore, "",
+ oras.WithNameValidation(nil))
if err != nil {
return nil, err
}
@@ -449,7 +558,7 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
},
Chart: chartSummary,
Prov: &descriptorPushSummary{}, // prevent nil references
- Ref: ref,
+ Ref: parsedRef.String(),
}
if operation.provData != nil {
result.Prov = &descriptorPushSummary{
@@ -459,6 +568,11 @@ func (c *Client) Push(data []byte, ref string, options ...PushOption) (*PushResu
}
fmt.Fprintf(c.out, "Pushed: %s\n", result.Ref)
fmt.Fprintf(c.out, "Digest: %s\n", result.Manifest.Digest)
+ if strings.Contains(parsedRef.Reference, "_") {
+ fmt.Fprintf(c.out, "%s contains an underscore.\n", result.Ref)
+ fmt.Fprint(c.out, registryUnderscoreMessage+"\n")
+ }
+
return result, err
}
@@ -475,3 +589,55 @@ func PushOptStrictMode(strictMode bool) PushOption {
operation.strictMode = strictMode
}
}
+
+// Tags provides a sorted list all semver compliant tags for a given repository
+func (c *Client) Tags(ref string) ([]string, error) {
+ parsedReference, err := registry.ParseReference(ref)
+ if err != nil {
+ return nil, err
+ }
+
+ repository := registryremote.Repository{
+ Reference: parsedReference,
+ Client: c.registryAuthorizer,
+ }
+
+ var registryTags []string
+
+ for {
+ registryTags, err = registry.Tags(ctx(c.out, c.debug), &repository)
+ if err != nil {
+ // Fallback to http based request
+ if !repository.PlainHTTP && strings.Contains(err.Error(), "server gave HTTP response") {
+ repository.PlainHTTP = true
+ continue
+ }
+ return nil, err
+ }
+
+ break
+
+ }
+
+ var tagVersions []*semver.Version
+ for _, tag := range registryTags {
+ // Change underscore (_) back to plus (+) for Helm
+ // See https://github.com/helm/helm/issues/10166
+ tagVersion, err := semver.StrictNewVersion(strings.ReplaceAll(tag, "_", "+"))
+ if err == nil {
+ tagVersions = append(tagVersions, tagVersion)
+ }
+ }
+
+ // Sort the collection
+ sort.Sort(sort.Reverse(semver.Collection(tagVersions)))
+
+ tags := make([]string, len(tagVersions))
+
+ for iTv, tv := range tagVersions {
+ tags[iTv] = tv.String()
+ }
+
+ return tags, nil
+
+}
diff --git a/vendor/helm.sh/helm/v3/internal/experimental/registry/constants.go b/vendor/helm.sh/helm/v3/pkg/registry/constants.go
index 876e4dc13..570b6f0d3 100644
--- a/vendor/helm.sh/helm/v3/internal/experimental/registry/constants.go
+++ b/vendor/helm.sh/helm/v3/pkg/registry/constants.go
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-package registry // import "helm.sh/helm/v3/internal/experimental/registry"
+package registry // import "helm.sh/helm/v3/pkg/registry"
const (
// OCIScheme is the URL scheme for OCI-based requests
OCIScheme = "oci"
// CredentialsFileBasename is the filename for auth credentials file
- CredentialsFileBasename = "registry.json"
+ CredentialsFileBasename = "registry/config.json"
// ConfigMediaType is the reserved media type for the Helm chart manifest config
ConfigMediaType = "application/vnd.cncf.helm.config.v1+json"
diff --git a/vendor/helm.sh/helm/v3/pkg/registry/util.go b/vendor/helm.sh/helm/v3/pkg/registry/util.go
new file mode 100644
index 000000000..47eed267f
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/registry/util.go
@@ -0,0 +1,131 @@
+/*
+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 registry // import "helm.sh/helm/v3/pkg/registry"
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/Masterminds/semver/v3"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ orascontext "oras.land/oras-go/pkg/context"
+ "oras.land/oras-go/pkg/registry"
+
+ "helm.sh/helm/v3/pkg/chart"
+ "helm.sh/helm/v3/pkg/chart/loader"
+)
+
+// IsOCI determines whether or not a URL is to be treated as an OCI URL
+func IsOCI(url string) bool {
+ return strings.HasPrefix(url, fmt.Sprintf("%s://", OCIScheme))
+}
+
+// ContainsTag determines whether a tag is found in a provided list of tags
+func ContainsTag(tags []string, tag string) bool {
+ for _, t := range tags {
+ if tag == t {
+ return true
+ }
+ }
+ return false
+}
+
+func GetTagMatchingVersionOrConstraint(tags []string, versionString string) (string, error) {
+ var constraint *semver.Constraints
+ if versionString == "" {
+ // If string is empty, set wildcard constraint
+ constraint, _ = semver.NewConstraint("*")
+ } else {
+ // when customer input exact version, check whether have exact match
+ // one first
+ for _, v := range tags {
+ if versionString == v {
+ return v, nil
+ }
+ }
+
+ // Otherwise set constraint to the string given
+ var err error
+ constraint, err = semver.NewConstraint(versionString)
+ if err != nil {
+ return "", err
+ }
+ }
+
+ // Otherwise try to find the first available version matching the string,
+ // in case it is a constraint
+ for _, v := range tags {
+ test, err := semver.NewVersion(v)
+ if err != nil {
+ continue
+ }
+ if constraint.Check(test) {
+ return v, nil
+ }
+ }
+
+ return "", errors.Errorf("Could not locate a version matching provided version string %s", versionString)
+}
+
+// extractChartMeta is used to extract a chart metadata from a byte array
+func extractChartMeta(chartData []byte) (*chart.Metadata, error) {
+ ch, err := loader.LoadArchive(bytes.NewReader(chartData))
+ if err != nil {
+ return nil, err
+ }
+ return ch.Metadata, nil
+}
+
+// ctx retrieves a fresh context.
+// disable verbose logging coming from ORAS (unless debug is enabled)
+func ctx(out io.Writer, debug bool) context.Context {
+ if !debug {
+ return orascontext.Background()
+ }
+ ctx := orascontext.WithLoggerFromWriter(context.Background(), out)
+ orascontext.GetLogger(ctx).Logger.SetLevel(logrus.DebugLevel)
+ return ctx
+}
+
+// parseReference will parse and validate the reference, and clean tags when
+// applicable tags are only cleaned when plus (+) signs are present, and are
+// converted to underscores (_) before pushing
+// See https://github.com/helm/helm/issues/10166
+func parseReference(raw string) (registry.Reference, error) {
+ // The sole possible reference modification is replacing plus (+) signs
+ // present in tags with underscores (_). To do this properly, we first
+ // need to identify a tag, and then pass it on to the reference parser
+ // NOTE: Passing immediately to the reference parser will fail since (+)
+ // signs are an invalid tag character, and simply replacing all plus (+)
+ // occurrences could invalidate other portions of the URI
+ parts := strings.Split(raw, ":")
+ if len(parts) > 1 && !strings.Contains(parts[len(parts)-1], "/") {
+ tag := parts[len(parts)-1]
+
+ if tag != "" {
+ // Replace any plus (+) signs with known underscore (_) conversion
+ newTag := strings.ReplaceAll(tag, "+", "_")
+ raw = strings.ReplaceAll(raw, tag, newTag)
+ }
+ }
+
+ return registry.ParseReference(raw)
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/releaseutil/kind_sorter.go b/vendor/helm.sh/helm/v3/pkg/releaseutil/kind_sorter.go
index a340dfc29..1d1874cfa 100644
--- a/vendor/helm.sh/helm/v3/pkg/releaseutil/kind_sorter.go
+++ b/vendor/helm.sh/helm/v3/pkg/releaseutil/kind_sorter.go
@@ -61,6 +61,7 @@ var InstallOrder KindSortOrder = []string{
"StatefulSet",
"Job",
"CronJob",
+ "IngressClass",
"Ingress",
"APIService",
}
@@ -71,6 +72,7 @@ var InstallOrder KindSortOrder = []string{
var UninstallOrder KindSortOrder = []string{
"APIService",
"Ingress",
+ "IngressClass",
"Service",
"CronJob",
"Job",
diff --git a/vendor/helm.sh/helm/v3/pkg/storage/driver/util.go b/vendor/helm.sh/helm/v3/pkg/storage/driver/util.go
index e5b846163..b5908e508 100644
--- a/vendor/helm.sh/helm/v3/pkg/storage/driver/util.go
+++ b/vendor/helm.sh/helm/v3/pkg/storage/driver/util.go
@@ -63,7 +63,7 @@ func decodeRelease(data string) (*rspb.Release, error) {
// For backwards compatibility with releases that were stored before
// compression was introduced we skip decompression if the
// gzip magic header is not found
- if bytes.Equal(b[0:3], magicGzip) {
+ if len(b) > 3 && bytes.Equal(b[0:3], magicGzip) {
r, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
return nil, err
diff --git a/vendor/helm.sh/helm/v3/pkg/storage/storage.go b/vendor/helm.sh/helm/v3/pkg/storage/storage.go
index 370fec4b4..0a18b34a0 100644
--- a/vendor/helm.sh/helm/v3/pkg/storage/storage.go
+++ b/vendor/helm.sh/helm/v3/pkg/storage/storage.go
@@ -177,7 +177,7 @@ func (s *Storage) removeLeastRecent(name string, max int) error {
relutil.SortByRevision(h)
lastDeployed, err := s.Deployed(name)
- if err != nil {
+ if err != nil && !errors.Is(err, driver.ErrNoDeployedReleases) {
return err
}
diff --git a/vendor/helm.sh/helm/v3/pkg/strvals/parser.go b/vendor/helm.sh/helm/v3/pkg/strvals/parser.go
index 457b99f94..d8c73d03c 100644
--- a/vendor/helm.sh/helm/v3/pkg/strvals/parser.go
+++ b/vendor/helm.sh/helm/v3/pkg/strvals/parser.go
@@ -29,6 +29,10 @@ import (
// ErrNotList indicates that a non-list was treated as a list.
var ErrNotList = errors.New("not a list")
+// MaxIndex is the maximum index that will be allowed by setIndex.
+// The default value 65536 = 1024 * 64
+var MaxIndex = 65536
+
// ToYAML takes a string of arguments and converts to a YAML document.
func ToYAML(s string) (string, error) {
m, err := Parse(s)
@@ -249,6 +253,9 @@ func setIndex(list []interface{}, index int, val interface{}) (l2 []interface{},
if index < 0 {
return list, fmt.Errorf("negative %d index not allowed", index)
}
+ if index > MaxIndex {
+ 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)
copy(newlist, list)
diff --git a/vendor/helm.sh/helm/v3/pkg/uploader/chart_uploader.go b/vendor/helm.sh/helm/v3/pkg/uploader/chart_uploader.go
new file mode 100644
index 000000000..d7e940406
--- /dev/null
+++ b/vendor/helm.sh/helm/v3/pkg/uploader/chart_uploader.go
@@ -0,0 +1,58 @@
+/*
+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 uploader
+
+import (
+ "fmt"
+ "io"
+ "net/url"
+
+ "github.com/pkg/errors"
+
+ "helm.sh/helm/v3/pkg/pusher"
+ "helm.sh/helm/v3/pkg/registry"
+)
+
+// ChartUploader handles uploading a chart.
+type ChartUploader struct {
+ // Out is the location to write warning and info messages.
+ Out io.Writer
+ // Pusher collection for the operation
+ Pushers pusher.Providers
+ // Options provide parameters to be passed along to the Pusher being initialized.
+ Options []pusher.Option
+ // RegistryClient is a client for interacting with registries.
+ RegistryClient *registry.Client
+}
+
+// UploadTo uploads a chart. Depending on the settings, it may also upload a provenance file.
+func (c *ChartUploader) UploadTo(ref, remote string) error {
+ u, err := url.Parse(remote)
+ if err != nil {
+ return errors.Errorf("invalid chart URL format: %s", remote)
+ }
+
+ if u.Scheme == "" {
+ return fmt.Errorf("scheme prefix missing from remote (e.g. \"%s://\")", registry.OCIScheme)
+ }
+
+ p, err := c.Pushers.ByScheme(u.Scheme)
+ if err != nil {
+ return err
+ }
+
+ return p.Push(ref, u.String(), c.Options...)
+}
diff --git a/vendor/helm.sh/helm/v3/pkg/gates/doc.go b/vendor/helm.sh/helm/v3/pkg/uploader/doc.go
index 762fdb8c6..45eacbbf5 100644
--- a/vendor/helm.sh/helm/v3/pkg/gates/doc.go
+++ b/vendor/helm.sh/helm/v3/pkg/uploader/doc.go
@@ -13,8 +13,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-/*Package gates provides a general tool for working with experimental feature gates.
+/*Package uploader provides a library for uploading charts.
-This provides convenience methods where the user can determine if certain experimental features are enabled.
+This package contains tools for uploading charts to registries.
*/
-package gates
+package uploader