Upgrade k8s package verison (#5358)

* upgrade k8s package version

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

* Script upgrade and code formatting.

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-11-15 14:56:38 +08:00
committed by GitHub
parent 5f91c1663a
commit 44167aa47a
3106 changed files with 321340 additions and 172080 deletions

View File

@@ -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"
@@ -102,11 +102,11 @@ type Configuration struct {
// TODO: This function is badly in need of a refactor.
// TODO: As part of the refactor the duplicate code in cmd/helm/template.go should be removed
// This code has to do with writing files to disk.
func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values, releaseName, outputDir string, subNotes, useReleaseName, includeCrds bool, pr postrender.PostRenderer, dryRun bool) ([]*release.Hook, *bytes.Buffer, string, error) {
func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Values, releaseName, outputDir string, subNotes, useReleaseName, includeCrds bool, pr postrender.PostRenderer, dryRun bool) ([]*release.Hook, *bytes.Buffer, string, error) {
hs := []*release.Hook{}
b := bytes.NewBuffer(nil)
caps, err := c.getCapabilities()
caps, err := cfg.getCapabilities()
if err != nil {
return hs, b, "", err
}
@@ -125,12 +125,12 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values
// is mocked. It is not up to the template author to decide when the user wants to
// connect to the cluster. So when the user says to dry run, respect the user's
// wishes and do not connect to the cluster.
if !dryRun && c.RESTClientGetter != nil {
rest, err := c.RESTClientGetter.ToRESTConfig()
if !dryRun && cfg.RESTClientGetter != nil {
restConfig, err := cfg.RESTClientGetter.ToRESTConfig()
if err != nil {
return hs, b, "", err
}
files, err2 = engine.RenderWithClient(ch, values, rest)
files, err2 = engine.RenderWithClient(ch, values, restConfig)
} else {
files, err2 = engine.Render(ch, values)
}
@@ -236,11 +236,11 @@ type RESTClientGetter interface {
type DebugLog func(format string, v ...interface{})
// capabilities builds a Capabilities from discovery information.
func (c *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
if c.Capabilities != nil {
return c.Capabilities, nil
func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
if cfg.Capabilities != nil {
return cfg.Capabilities, nil
}
dc, err := c.RESTClientGetter.ToDiscoveryClient()
dc, err := cfg.RESTClientGetter.ToDiscoveryClient()
if err != nil {
return nil, errors.Wrap(err, "could not get Kubernetes discovery client")
}
@@ -258,27 +258,28 @@ func (c *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
apiVersions, err := GetVersionSet(dc)
if err != nil {
if discovery.IsGroupDiscoveryFailedError(err) {
c.Log("WARNING: The Kubernetes server has an orphaned API service. Server reports: %s", err)
c.Log("WARNING: To fix this, kubectl delete apiservice <service-name>")
cfg.Log("WARNING: The Kubernetes server has an orphaned API service. Server reports: %s", err)
cfg.Log("WARNING: To fix this, kubectl delete apiservice <service-name>")
} else {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
}
}
c.Capabilities = &chartutil.Capabilities{
cfg.Capabilities = &chartutil.Capabilities{
APIVersions: apiVersions,
KubeVersion: chartutil.KubeVersion{
Version: kubeVersion.GitVersion,
Major: kubeVersion.Major,
Minor: kubeVersion.Minor,
},
HelmVersion: chartutil.DefaultCapabilities.HelmVersion,
}
return c.Capabilities, nil
return cfg.Capabilities, nil
}
// KubernetesClientSet creates a new kubernetes ClientSet based on the configuration
func (c *Configuration) KubernetesClientSet() (kubernetes.Interface, error) {
conf, err := c.RESTClientGetter.ToRESTConfig()
func (cfg *Configuration) KubernetesClientSet() (kubernetes.Interface, error) {
conf, err := cfg.RESTClientGetter.ToRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "unable to generate config for kubernetes client")
}
@@ -290,20 +291,20 @@ func (c *Configuration) KubernetesClientSet() (kubernetes.Interface, error) {
//
// If the configuration has a Timestamper on it, that will be used.
// Otherwise, this will use time.Now().
func (c *Configuration) Now() time.Time {
func (cfg *Configuration) Now() time.Time {
return Timestamper()
}
func (c *Configuration) releaseContent(name string, version int) (*release.Release, error) {
func (cfg *Configuration) releaseContent(name string, version int) (*release.Release, error) {
if err := chartutil.ValidateReleaseName(name); err != nil {
return nil, errors.Errorf("releaseContent: Release name is invalid: %s", name)
}
if version <= 0 {
return c.Releases.Last(name)
return cfg.Releases.Last(name)
}
return c.Releases.Get(name, version)
return cfg.Releases.Get(name, version)
}
// GetVersionSet retrieves a set of available k8s API versions
@@ -355,14 +356,14 @@ func GetVersionSet(client discovery.ServerResourcesInterface) (chartutil.Version
}
// recordRelease with an update operation in case reuse has been set.
func (c *Configuration) recordRelease(r *release.Release) {
if err := c.Releases.Update(r); err != nil {
c.Log("warning: Failed to update release %s: %s", r.Name, err)
func (cfg *Configuration) recordRelease(r *release.Release) {
if err := cfg.Releases.Update(r); err != nil {
cfg.Log("warning: Failed to update release %s: %s", r.Name, err)
}
}
// Init initializes the action configuration
func (c *Configuration) Init(getter genericclioptions.RESTClientGetter, namespace, helmDriver string, log DebugLog) error {
func (cfg *Configuration) Init(getter genericclioptions.RESTClientGetter, namespace, helmDriver string, log DebugLog) error {
kc := kube.New(getter)
kc.Log = log
@@ -383,8 +384,8 @@ func (c *Configuration) Init(getter genericclioptions.RESTClientGetter, namespac
store = storage.Init(d)
case "memory":
var d *driver.Memory
if c.Releases != nil {
if mem, ok := c.Releases.Driver.(*driver.Memory); ok {
if cfg.Releases != nil {
if mem, ok := cfg.Releases.Driver.(*driver.Memory); ok {
// This function can be called more than once (e.g., helm list --all-namespaces).
// If a memory driver was already initialized, re-use it but set the possibly new namespace.
// We re-use it in case some releases where already created in the existing memory driver.
@@ -411,10 +412,10 @@ func (c *Configuration) Init(getter genericclioptions.RESTClientGetter, namespac
panic("Unknown driver in HELM_DRIVER: " + helmDriver)
}
c.RESTClientGetter = getter
c.KubeClient = kc
c.Releases = store
c.Log = log
cfg.RESTClientGetter = getter
cfg.KubeClient = kc
cfg.Releases = store
cfg.Log = log
return nil
}

View File

@@ -1,63 +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 action
import (
"fmt"
"io"
"path/filepath"
"helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chartutil"
)
// ChartExport performs a chart export operation.
type ChartExport struct {
cfg *Configuration
Destination string
}
// NewChartExport creates a new ChartExport object with the given configuration.
func NewChartExport(cfg *Configuration) *ChartExport {
return &ChartExport{
cfg: cfg,
}
}
// Run executes the chart export operation
func (a *ChartExport) Run(out io.Writer, ref string) error {
r, err := registry.ParseReference(ref)
if err != nil {
return err
}
ch, err := a.cfg.RegistryClient.LoadChart(r)
if err != nil {
return err
}
// Save the chart to local destination directory
err = chartutil.SaveDir(ch, a.Destination)
if err != nil {
return err
}
d := filepath.Join(a.Destination, ch.Metadata.Name)
fmt.Fprintf(out, "Exported chart to %s/\n", d)
return nil
}

View File

@@ -1,38 +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 action
import (
"io"
)
// ChartList performs a chart list operation.
type ChartList struct {
cfg *Configuration
}
// NewChartList creates a new ChartList object with the given configuration.
func NewChartList(cfg *Configuration) *ChartList {
return &ChartList{
cfg: cfg,
}
}
// Run executes the chart list operation
func (a *ChartList) Run(out io.Writer) error {
return a.cfg.RegistryClient.PrintChartTable()
}

View File

@@ -1,44 +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 action
import (
"io"
"helm.sh/helm/v3/internal/experimental/registry"
)
// ChartPull performs a chart pull operation.
type ChartPull struct {
cfg *Configuration
}
// NewChartPull creates a new ChartPull object with the given configuration.
func NewChartPull(cfg *Configuration) *ChartPull {
return &ChartPull{
cfg: cfg,
}
}
// Run executes the chart pull operation
func (a *ChartPull) Run(out io.Writer, ref string) error {
r, err := registry.ParseReference(ref)
if err != nil {
return err
}
return a.cfg.RegistryClient.PullChartToCache(r)
}

View File

@@ -1,44 +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 action
import (
"io"
"helm.sh/helm/v3/internal/experimental/registry"
)
// ChartPush performs a chart push operation.
type ChartPush struct {
cfg *Configuration
}
// NewChartPush creates a new ChartPush object with the given configuration.
func NewChartPush(cfg *Configuration) *ChartPush {
return &ChartPush{
cfg: cfg,
}
}
// Run executes the chart push operation
func (a *ChartPush) Run(out io.Writer, ref string) error {
r, err := registry.ParseReference(ref)
if err != nil {
return err
}
return a.cfg.RegistryClient.PushChart(r)
}

View File

@@ -1,44 +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 action
import (
"io"
"helm.sh/helm/v3/internal/experimental/registry"
)
// ChartRemove performs a chart remove operation.
type ChartRemove struct {
cfg *Configuration
}
// NewChartRemove creates a new ChartRemove object with the given configuration.
func NewChartRemove(cfg *Configuration) *ChartRemove {
return &ChartRemove{
cfg: cfg,
}
}
// Run executes the chart remove operation
func (a *ChartRemove) Run(out io.Writer, ref string) error {
r, err := registry.ParseReference(ref)
if err != nil {
return err
}
return a.cfg.RegistryClient.RemoveChart(r)
}

View File

@@ -1,51 +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 action
import (
"io"
"helm.sh/helm/v3/internal/experimental/registry"
"helm.sh/helm/v3/pkg/chart"
)
// ChartSave performs a chart save operation.
type ChartSave struct {
cfg *Configuration
}
// NewChartSave creates a new ChartSave object with the given configuration.
func NewChartSave(cfg *Configuration) *ChartSave {
return &ChartSave{
cfg: cfg,
}
}
// Run executes the chart save operation
func (a *ChartSave) Run(out io.Writer, ch *chart.Chart, ref string) error {
r, err := registry.ParseReference(ref)
if err != nil {
return err
}
// If no tag is present, use the chart version
if r.Tag == "" {
r.Tag = ch.Metadata.Version
}
return a.cfg.RegistryClient.SaveChart(ch, r)
}

View File

@@ -37,11 +37,14 @@ type Dependency struct {
Verify bool
Keyring string
SkipRefresh bool
ColumnWidth uint
}
// NewDependency creates a new Dependency object with the given configuration.
func NewDependency() *Dependency {
return &Dependency{}
return &Dependency{
ColumnWidth: 80,
}
}
// List executes 'helm dependency list'.
@@ -181,7 +184,7 @@ func statArchiveForStatus(archive string, dep *chart.Dependency) string {
// printDependencies prints all of the dependencies in the yaml file.
func (d *Dependency) printDependencies(chartpath string, out io.Writer, c *chart.Chart) {
table := uitable.New()
table.MaxColWidth = 80
table.MaxColWidth = d.ColumnWidth
table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS")
for _, row := range c.Metadata.Dependencies {
table.AddRow(row.Name, row.Version, row.Repository, d.dependencyStatus(chartpath, row, c))
@@ -190,7 +193,7 @@ func (d *Dependency) printDependencies(chartpath string, out io.Writer, c *chart
}
// printMissing prints warnings about charts that are present on disk, but are
// not in Charts.yaml.
// not in Chart.yaml.
func (d *Dependency) printMissing(chartpath string, out io.Writer, reqs []*chart.Dependency) {
folder := filepath.Join(chartpath, "charts/*")
files, err := filepath.Glob(folder)

View File

@@ -18,6 +18,7 @@ package action
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/url"
@@ -25,6 +26,7 @@ import (
"path"
"path/filepath"
"strings"
"sync"
"text/template"
"time"
@@ -44,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"
@@ -51,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
@@ -104,6 +100,8 @@ type Install struct {
// OutputDir/<ReleaseName>
UseReleaseName bool
PostRenderer postrender.PostRenderer
// Lock to control raceconditions when the process receives a SIGTERM
Lock sync.Mutex
}
// ChartPathOptions captures common options used for controlling chart paths
@@ -119,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 {
@@ -174,7 +179,14 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
// Run executes the installation
//
// If DryRun is set to true, this will prepare the release, but not install it
func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
ctx := context.Background()
return i.RunWithContext(ctx, chrt, vals)
}
// Run executes the installation with Context
func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
// Check reachability of cluster unless in client-only mode (e.g. `helm template` without `--validate`)
if !i.ClientOnly {
if err := i.cfg.KubeClient.IsReachable(); err != nil {
@@ -186,6 +198,10 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
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 {
@@ -214,10 +230,6 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
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
@@ -227,7 +239,7 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
return nil, err
}
//special case for helm template --is-upgrade
// special case for helm template --is-upgrade
isUpgrade := i.IsUpgrade && i.DryRun
options := chartutil.ReleaseOptions{
Name: i.ReleaseName,
@@ -331,11 +343,23 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
// not working.
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, doneChan, rel)
result := <-rChan
//start preformInstall go routine
return result.r, result.e
}
func (i *Install) performInstall(c chan<- resultMessage, rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) {
// pre-install hooks
if !i.DisableHooks {
if err := i.cfg.execHook(rel, release.HookPreInstall, i.Timeout); err != nil {
return i.failRelease(rel, fmt.Errorf("failed pre-install: %s", err))
i.reportToRun(c, rel, fmt.Errorf("failed pre-install: %s", err))
return
}
}
@@ -344,29 +368,34 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
// to true, since that is basically an upgrade operation.
if len(toBeAdopted) == 0 && len(resources) > 0 {
if _, err := i.cfg.KubeClient.Create(resources); err != nil {
return i.failRelease(rel, err)
i.reportToRun(c, rel, err)
return
}
} else if len(resources) > 0 {
if _, err := i.cfg.KubeClient.Update(toBeAdopted, resources, false); err != nil {
return i.failRelease(rel, err)
i.reportToRun(c, rel, err)
return
}
}
if i.Wait {
if i.WaitForJobs {
if err := i.cfg.KubeClient.WaitWithJobs(resources, i.Timeout); err != nil {
return i.failRelease(rel, err)
i.reportToRun(c, rel, err)
return
}
} else {
if err := i.cfg.KubeClient.Wait(resources, i.Timeout); err != nil {
return i.failRelease(rel, err)
i.reportToRun(c, rel, err)
return
}
}
}
if !i.DisableHooks {
if err := i.cfg.execHook(rel, release.HookPostInstall, i.Timeout); err != nil {
return i.failRelease(rel, fmt.Errorf("failed post-install: %s", err))
i.reportToRun(c, rel, fmt.Errorf("failed post-install: %s", err))
return
}
}
@@ -387,9 +416,25 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
i.cfg.Log("failed to record the release: %s", err)
}
return rel, nil
i.reportToRun(c, rel, nil)
}
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()
if err != nil {
rel, err = i.failRelease(rel, err)
}
c <- resultMessage{r: rel, e: err}
i.Lock.Unlock()
}
func (i *Install) failRelease(rel *release.Release, err error) (*release.Release, error) {
rel.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", i.ReleaseName, err.Error()))
if i.Atomic {
@@ -417,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
}
@@ -632,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)
@@ -662,7 +709,9 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
},
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
RegistryClient: c.registryClient,
}
if c.Verify {
dl.Verify = downloader.VerifyAlways
}
@@ -716,5 +765,6 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
if version != "" {
atVersion = fmt.Sprintf(" at version %q", version)
}
return filename, errors.Errorf("failed to download %q%s (hint: running `helm repo update` may help)", name, atVersion)
return filename, errors.Errorf("failed to download %q%s", name, atVersion)
}

View File

@@ -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{}
@@ -96,7 +107,7 @@ func lintChart(path string, vals map[string]interface{}, namespace string, stric
return linter, errors.Wrap(err, "unable to extract tarball")
}
files, err := ioutil.ReadDir(tempDir)
files, err := os.ReadDir(tempDir)
if err != nil {
return linter, errors.Wrapf(err, "unable to read temporary output directory %s", tempDir)
}

View File

@@ -29,6 +29,7 @@ import (
"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"
)
@@ -86,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 strings.HasPrefix(chartRef, "oci://") {
if p.Version == "" {
return out.String(), errors.Errorf("--version flag is explicitly required for OCI registries")
}
if registry.IsOCI(chartRef) {
c.Options = append(c.Options,
getter.WithRegistryClient(p.cfg.RegistryClient),
getter.WithTagName(p.Version))
getter.WithRegistryClient(p.cfg.RegistryClient))
}
if p.Verify {

View File

@@ -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)
}

View File

@@ -18,6 +18,8 @@ package action
import (
"io"
"helm.sh/helm/v3/pkg/registry"
)
// RegistryLogin performs a registry login operation.
@@ -34,5 +36,8 @@ func NewRegistryLogin(cfg *Configuration) *RegistryLogin {
// 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, username, password, insecure)
return a.cfg.RegistryClient.Login(
hostname,
registry.LoginOptBasicAuth(username, password),
registry.LoginOptInsecure(insecure))
}

View File

@@ -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 {

View File

@@ -17,6 +17,7 @@ limitations under the License.
package action
import (
"bytes"
"fmt"
"strings"
@@ -41,6 +42,8 @@ const (
ShowValues ShowOutputFormat = "values"
// ShowReadme is the format which only shows the chart's README
ShowReadme ShowOutputFormat = "readme"
// ShowCRDs is the format which only shows the chart's CRDs
ShowCRDs ShowOutputFormat = "crds"
)
var readmeFileNames = []string{"readme.md", "readme.txt", "readme"}
@@ -61,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 {
@@ -106,14 +121,25 @@ func (s *Show) Run(chartpath string) (string, error) {
}
if s.OutputFormat == ShowReadme || s.OutputFormat == ShowAll {
if s.OutputFormat == ShowAll {
fmt.Fprintln(&out, "---")
}
readme := findReadme(s.chart.Files)
if readme == nil {
return out.String(), nil
if readme != nil {
if s.OutputFormat == ShowAll {
fmt.Fprintln(&out, "---")
}
fmt.Fprintf(&out, "%s\n", readme.Data)
}
}
if s.OutputFormat == ShowCRDs || s.OutputFormat == ShowAll {
crds := s.chart.CRDObjects()
if len(crds) > 0 {
if s.OutputFormat == ShowAll && !bytes.HasPrefix(crds[0].File.Data, []byte("---")) {
fmt.Fprintln(&out, "---")
}
for _, crd := range crds {
fmt.Fprintf(&out, "%s\n", string(crd.File.Data))
}
}
fmt.Fprintf(&out, "%s\n", readme.Data)
}
return out.String(), nil
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/kube"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
helmtime "helm.sh/helm/v3/pkg/time"
@@ -37,6 +38,7 @@ type Uninstall struct {
DisableHooks bool
DryRun bool
KeepHistory bool
Wait bool
Timeout time.Duration
Description string
}
@@ -110,13 +112,21 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
u.cfg.Log("uninstall: Failed to store updated release: %s", err)
}
kept, errs := u.deleteRelease(rel)
deletedResources, kept, errs := u.deleteRelease(rel)
if kept != "" {
kept = "These resources were kept due to the resource policy:\n" + kept
}
res.Info = kept
if u.Wait {
if kubeClient, ok := u.cfg.KubeClient.(kube.InterfaceExt); ok {
if err := kubeClient.WaitForDelete(deletedResources, u.Timeout); err != nil {
errs = append(errs, err)
}
}
}
if !u.DisableHooks {
if err := u.cfg.execHook(rel, release.HookPostDelete, u.Timeout); err != nil {
errs = append(errs, err)
@@ -172,12 +182,12 @@ func joinErrors(errs []error) string {
return strings.Join(es, "; ")
}
// deleteRelease deletes the release and returns manifests that were kept in the deletion process
func (u *Uninstall) deleteRelease(rel *release.Release) (string, []error) {
// deleteRelease deletes the release and returns list of delete resources and manifests that were kept in the deletion process
func (u *Uninstall) deleteRelease(rel *release.Release) (kube.ResourceList, string, []error) {
var errs []error
caps, err := u.cfg.getCapabilities()
if err != nil {
return rel.Manifest, []error{errors.Wrap(err, "could not get apiVersions from Kubernetes")}
return nil, rel.Manifest, []error{errors.Wrap(err, "could not get apiVersions from Kubernetes")}
}
manifests := releaseutil.SplitManifests(rel.Manifest)
@@ -187,7 +197,7 @@ func (u *Uninstall) deleteRelease(rel *release.Release) (string, []error) {
// FIXME: One way to delete at this point would be to try a label-based
// deletion. The problem with this is that we could get a false positive
// and delete something that was not legitimately part of this release.
return rel.Manifest, []error{errors.Wrap(err, "corrupted release record. You must manually delete the resources")}
return nil, rel.Manifest, []error{errors.Wrap(err, "corrupted release record. You must manually delete the resources")}
}
filesToKeep, filesToDelete := filterManifestsToKeep(files)
@@ -203,10 +213,10 @@ func (u *Uninstall) deleteRelease(rel *release.Release) (string, []error) {
resources, err := u.cfg.KubeClient.Build(strings.NewReader(builder.String()), false)
if err != nil {
return "", []error{errors.Wrap(err, "unable to build kubernetes objects for delete")}
return nil, "", []error{errors.Wrap(err, "unable to build kubernetes objects for delete")}
}
if len(resources) > 0 {
_, errs = u.cfg.KubeClient.Delete(resources)
}
return kept, errs
return resources, kept, errs
}

View File

@@ -21,6 +21,7 @@ import (
"context"
"fmt"
"strings"
"sync"
"time"
"github.com/pkg/errors"
@@ -98,17 +99,35 @@ type Upgrade struct {
PostRenderer postrender.PostRenderer
// DisableOpenAPIValidation controls whether OpenAPI validation is enforced.
DisableOpenAPIValidation bool
// Get missing dependencies
DependencyUpdate bool
// Lock to control raceconditions when the process receives a SIGTERM
Lock sync.Mutex
}
type resultMessage struct {
r *release.Release
e error
}
// 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.
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)
}
// 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
}
@@ -129,7 +148,7 @@ func (u *Upgrade) Run(name string, chart *chart.Chart, vals map[string]interface
u.cfg.Releases.MaxHistory = u.MaxHistory
u.cfg.Log("performing update for %s", name)
res, err := u.performUpgrade(currentRelease, upgradedRelease)
res, err := u.performUpgrade(ctx, currentRelease, upgradedRelease)
if err != nil {
return res, err
}
@@ -241,7 +260,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
return currentRelease, upgradedRelease, err
}
func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Release) (*release.Release, error) {
func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedRelease *release.Release) (*release.Release, error) {
current, err := u.cfg.KubeClient.Build(bytes.NewBufferString(originalRelease.Manifest), false)
if err != nil {
// Checking for removed Kubernetes API error so can provide a more informative error message to the user
@@ -304,11 +323,51 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
if err := u.cfg.Releases.Create(upgradedRelease); err != nil {
return nil, err
}
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:
return result.r, result.e
case result := <-ctxChan:
return result.r, result.e
}
}
// Function used to lock the Mutex, this is important for the case when the atomic flag is set.
// In that case the upgrade will finish before the rollback is finished so it is necessary to wait for the rollback to finish.
// The rollback will be trigger by the function failRelease
func (u *Upgrade) reportToPerformUpgrade(c chan<- resultMessage, rel *release.Release, created kube.ResourceList, err error) {
u.Lock.Lock()
if err != nil {
rel, err = u.failRelease(rel, created, err)
}
c <- resultMessage{r: rel, e: err}
u.Lock.Unlock()
}
// Setup listener for SIGINT and SIGTERM
func (u *Upgrade) handleContext(ctx context.Context, done chan interface{}, c chan<- resultMessage, upgradedRelease *release.Release) {
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
}
}
func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release) {
// pre-upgrade hooks
if !u.DisableHooks {
if err := u.cfg.execHook(upgradedRelease, release.HookPreUpgrade, u.Timeout); err != nil {
return u.failRelease(upgradedRelease, kube.ResourceList{}, fmt.Errorf("pre-upgrade hooks failed: %s", err))
u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, fmt.Errorf("pre-upgrade hooks failed: %s", err))
return
}
} else {
u.cfg.Log("upgrade hooks disabled for %s", upgradedRelease.Name)
@@ -317,7 +376,8 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
results, err := u.cfg.KubeClient.Update(current, target, u.Force)
if err != nil {
u.cfg.recordRelease(originalRelease)
return u.failRelease(upgradedRelease, results.Created, err)
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
return
}
if u.Recreate {
@@ -334,12 +394,14 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
if u.WaitForJobs {
if err := u.cfg.KubeClient.WaitWithJobs(target, u.Timeout); err != nil {
u.cfg.recordRelease(originalRelease)
return u.failRelease(upgradedRelease, results.Created, err)
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
return
}
} else {
if err := u.cfg.KubeClient.Wait(target, u.Timeout); err != nil {
u.cfg.recordRelease(originalRelease)
return u.failRelease(upgradedRelease, results.Created, err)
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
return
}
}
}
@@ -347,7 +409,8 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
// post-upgrade hooks
if !u.DisableHooks {
if err := u.cfg.execHook(upgradedRelease, release.HookPostUpgrade, u.Timeout); err != nil {
return u.failRelease(upgradedRelease, results.Created, fmt.Errorf("post-upgrade hooks failed: %s", err))
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, fmt.Errorf("post-upgrade hooks failed: %s", err))
return
}
}
@@ -360,8 +423,7 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
} else {
upgradedRelease.Info.Description = "Upgrade complete"
}
return upgradedRelease, nil
u.reportToPerformUpgrade(c, upgradedRelease, nil, nil)
}
func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, err error) (*release.Release, error) {

View File

@@ -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.