mirror of
https://github.com/helm/helm.git
synced 2026-05-28 04:35:48 -04:00
Merge branch 'master' into add-390x-support
This commit is contained in:
commit
e4c0eb8720
65 changed files with 913 additions and 198 deletions
230
KEYS
230
KEYS
|
|
@ -622,3 +622,233 @@ BlA4kJPTfla4LmKRg/T/xow/naen/aM9mQCs7k2UAoeqNZ6IfQ6G5BZ81H9JNvHC
|
|||
beriLZDBuRy1LJRjBmZEz+UDBgZoR9oz5DOLh8dGVpkt
|
||||
=HZO9
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
pub rsa4096 2014-05-13 [SCEA]
|
||||
ABA2529598F6626C420D335B62F49E747D911B60
|
||||
uid [ unknown] Matt Butcher <matt.butcher@microsoft.com>
|
||||
sig 3 62F49E747D911B60 2017-08-11 Matt Butcher <matt.butcher@microsoft.com>
|
||||
sig 461449C25E36B98E 2018-12-12 Matthew Farina <matt@mattfarina.com>
|
||||
sig 1EF612347F8A9958 2018-12-12 Adam Reese <adam@reese.io>
|
||||
sig 2CDBBFBB37AE822A 2018-12-12 Adnan Abdulhussein <prydonius@gmail.com>
|
||||
uid [ unknown] technosophos (keybase.io/technosophos) <technosophos@gmail.com>
|
||||
sig 3 62F49E747D911B60 2016-10-24 Matt Butcher <matt.butcher@microsoft.com>
|
||||
sig 461449C25E36B98E 2018-12-12 Matthew Farina <matt@mattfarina.com>
|
||||
sig 1EF612347F8A9958 2018-12-12 Adam Reese <adam@reese.io>
|
||||
sig 2CDBBFBB37AE822A 2018-12-12 Adnan Abdulhussein <prydonius@gmail.com>
|
||||
uid [ unknown] keybase.io/technosophos <technosophos@keybase.io>
|
||||
sig 3 62F49E747D911B60 2014-05-13 Matt Butcher <matt.butcher@microsoft.com>
|
||||
sig 461449C25E36B98E 2018-12-12 Matthew Farina <matt@mattfarina.com>
|
||||
sig 1EF612347F8A9958 2018-12-12 Adam Reese <adam@reese.io>
|
||||
sig 2CDBBFBB37AE822A 2018-12-12 Adnan Abdulhussein <prydonius@gmail.com>
|
||||
sub rsa2048 2014-05-13 [S] [expires: 2022-05-11]
|
||||
sig 62F49E747D911B60 2014-05-13 Matt Butcher <matt.butcher@microsoft.com>
|
||||
sub rsa2048 2014-05-13 [E] [expires: 2022-05-11]
|
||||
sig 62F49E747D911B60 2014-05-13 Matt Butcher <matt.butcher@microsoft.com>
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: GPGTools - https://gpgtools.org
|
||||
|
||||
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
|
||||
=nEJu
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
|
|
|||
23
Makefile
23
Makefile
|
|
@ -1,7 +1,8 @@
|
|||
BINDIR := $(CURDIR)/bin
|
||||
DIST_DIRS := find * -type d -exec
|
||||
TARGETS := darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64
|
||||
BINNAME ?= helm
|
||||
BINDIR := $(CURDIR)/bin
|
||||
DIST_DIRS := find * -type d -exec
|
||||
TARGETS := darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64
|
||||
TARGET_OBJS ?= darwin-amd64.tar.gz darwin-amd64.tar.gz.sha256 linux-amd64.tar.gz linux-amd64.tar.gz.sha256 linux-386.tar.gz linux-386.tar.gz.sha256 linux-arm.tar.gz linux-arm.tar.gz.sha256 linux-arm64.tar.gz linux-arm64.tar.gz.sha256 linux-ppc64le.tar.gz linux-ppc64le.tar.gz.sha256 windows-amd64.zip windows-amd64.zip.sha256
|
||||
BINNAME ?= helm
|
||||
|
||||
GOPATH = $(shell go env GOPATH)
|
||||
DEP = $(GOPATH)/bin/dep
|
||||
|
|
@ -138,6 +139,20 @@ dist:
|
|||
$(DIST_DIRS) zip -r helm-${VERSION}-{}.zip {} \; \
|
||||
)
|
||||
|
||||
.PHONY: fetch-dist
|
||||
fetch-dist:
|
||||
mkdir -p _dist
|
||||
cd _dist && \
|
||||
for obj in ${TARGET_OBJS} ; do \
|
||||
curl -sSL -o helm-${VERSION}-$${obj} https://get.helm.sh/helm-${VERSION}-$${obj} ; \
|
||||
done
|
||||
|
||||
.PHONY: sign
|
||||
sign:
|
||||
for f in _dist/*.{gz,zip,sha256} ; do \
|
||||
gpg --armor --detach-sign $${f} ; \
|
||||
done
|
||||
|
||||
.PHONY: checksum
|
||||
checksum:
|
||||
for f in _dist/*.{gz,zip} ; do \
|
||||
|
|
|
|||
1
OWNERS
1
OWNERS
|
|
@ -4,6 +4,7 @@ maintainers:
|
|||
- fibonacci1729
|
||||
- hickeyma
|
||||
- jdolitsky
|
||||
- marckhouzam
|
||||
- mattfarina
|
||||
- michelleN
|
||||
- prydonius
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[](https://circleci.com/gh/helm/helm)
|
||||
[](https://goreportcard.com/report/github.com/helm/helm)
|
||||
[](https://godoc.org/helm.sh/helm)
|
||||
[](https://pkg.go.dev/helm.sh/helm/v3)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/3131)
|
||||
|
||||
Helm is a tool for managing Charts. Charts are packages of pre-configured Kubernetes resources.
|
||||
|
|
@ -37,19 +37,19 @@ Unpack the `helm` binary and add it to your PATH and you are good to go!
|
|||
|
||||
If you want to use a package manager:
|
||||
|
||||
- [Homebrew](https://brew.sh/) users can use `brew install kubernetes-helm`.
|
||||
- [Homebrew](https://brew.sh/) users can use `brew install helm`.
|
||||
- [Chocolatey](https://chocolatey.org/) users can use `choco install kubernetes-helm`.
|
||||
- [Scoop](https://scoop.sh/) users can use `scoop install helm`.
|
||||
- [GoFish](https://gofi.sh/) users can use `gofish install helm`.
|
||||
|
||||
To rapidly get Helm up and running, start with the [Quick Start Guide](https://docs.helm.sh/using_helm/#quickstart-guide).
|
||||
|
||||
See the [installation guide](https://docs.helm.sh/using_helm/#installing-helm) for more options,
|
||||
See the [installation guide](https://helm.sh/docs/intro/install/) for more options,
|
||||
including installing pre-releases.
|
||||
|
||||
## Docs
|
||||
|
||||
Get started with the [Quick Start guide](https://docs.helm.sh/using_helm/#quickstart-guide) or plunge into the [complete documentation](https://docs.helm.sh)
|
||||
Get started with the [Quick Start guide](https://helm.sh/docs/intro/quickstart/) or plunge into the [complete documentation](https://helm.sh/docs)
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
|
|||
func createTestingMetadata(name, baseURL string) *chart.Chart {
|
||||
return &chart.Chart{
|
||||
Metadata: &chart.Metadata{
|
||||
APIVersion: chart.APIVersionV1,
|
||||
APIVersion: chart.APIVersionV2,
|
||||
Name: name,
|
||||
Version: "1.2.3",
|
||||
Dependencies: []*chart.Dependency{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"helm.sh/helm/v3/pkg/cli"
|
||||
|
||||
|
|
@ -55,8 +56,18 @@ type envOptions struct {
|
|||
}
|
||||
|
||||
func (o *envOptions) run(out io.Writer) error {
|
||||
for k, v := range o.settings.EnvVars() {
|
||||
fmt.Printf("%s=\"%s\"\n", k, v)
|
||||
envVars := o.settings.EnvVars()
|
||||
|
||||
// Sort the variables by alphabetical order.
|
||||
// This allows for a constant output across calls to 'helm env'.
|
||||
var keys []string
|
||||
for k := range envVars {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
fmt.Printf("%s=\"%s\"\n", k, envVars[k])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
|
|
@ -130,11 +131,12 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
func addInstallFlags(f *pflag.FlagSet, client *action.Install, valueOpts *values.Options) {
|
||||
f.BoolVar(&client.DryRun, "dry-run", false, "simulate an install")
|
||||
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install")
|
||||
f.BoolVar(&client.Replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production")
|
||||
f.BoolVar(&client.Replace, "replace", false, "re-use the given name, only if that name is a deleted release which remains in the history. This is unsafe in production")
|
||||
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
|
||||
f.BoolVar(&client.Wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as --timeout")
|
||||
f.BoolVarP(&client.GenerateName, "generate-name", "g", false, "generate the name (and omit the NAME parameter)")
|
||||
f.StringVar(&client.NameTemplate, "name-template", "", "specify template used to name the release")
|
||||
f.StringVar(&client.Description, "description", "", "add a custom description")
|
||||
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored")
|
||||
f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "run helm dependency update before installing the chart")
|
||||
f.BoolVar(&client.Atomic, "atomic", false, "if set, installation process purges chart on fail. The --wait flag will be set automatically if --atomic is used")
|
||||
|
|
@ -181,6 +183,10 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if chartRequested.Metadata.Deprecated {
|
||||
fmt.Fprintln(out, "WARNING: This chart is deprecated")
|
||||
}
|
||||
|
||||
if req := chartRequested.Metadata.Dependencies; req != nil {
|
||||
// If CheckDependencies returns an error, we have unfulfilled dependencies.
|
||||
// As of Helm 2.4.0, this is treated as a stopping condition:
|
||||
|
|
|
|||
|
|
@ -183,6 +183,12 @@ func TestInstall(t *testing.T) {
|
|||
wantError: true,
|
||||
golden: "output/subchart-schema-cli-negative.txt",
|
||||
},
|
||||
// Install deprecated chart
|
||||
{
|
||||
name: "install with warning about deprecated chart",
|
||||
cmd: "install aeneas testdata/testcharts/deprecated --namespace default",
|
||||
golden: "output/deprecated-chart.txt",
|
||||
},
|
||||
}
|
||||
|
||||
runTestActionCmd(t, tests)
|
||||
|
|
|
|||
|
|
@ -77,12 +77,15 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
client.SetStateMask()
|
||||
|
||||
results, err := client.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if client.Short {
|
||||
for _, res := range results {
|
||||
fmt.Fprintln(out, res.Name)
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
return outfmt.Write(out, newReleaseListWriter(results))
|
||||
|
|
@ -94,7 +97,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
|
||||
f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
|
||||
f.BoolVarP(&client.All, "all", "a", false, "show all releases, not just the ones marked deployed or failed")
|
||||
f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases")
|
||||
f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases (if 'helm uninstall --keep-history' was used)")
|
||||
f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases")
|
||||
f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled")
|
||||
f.BoolVar(&client.Deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled")
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
|
|||
func manuallyProcessArgs(args []string) ([]string, []string) {
|
||||
known := []string{}
|
||||
unknown := []string{}
|
||||
kvargs := []string{"--kube-context", "--namespace", "--kubeconfig", "--registry-config", "--repository-cache", "--repository-config"}
|
||||
kvargs := []string{"--kube-context", "--namespace", "-n", "--kubeconfig", "--registry-config", "--repository-cache", "--repository-config"}
|
||||
knownArg := func(a string) bool {
|
||||
for _, pre := range kvargs {
|
||||
if strings.HasPrefix(a, pre+"=") {
|
||||
|
|
@ -136,13 +136,26 @@ func manuallyProcessArgs(args []string) ([]string, []string) {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
isKnown := func(v string) string {
|
||||
for _, i := range kvargs {
|
||||
if i == v {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
switch a := args[i]; a {
|
||||
case "--debug":
|
||||
known = append(known, a)
|
||||
case "--kube-context", "--namespace", "-n", "--kubeconfig", "--registry-config", "--repository-cache", "--repository-config":
|
||||
known = append(known, a, args[i+1])
|
||||
case isKnown(a):
|
||||
known = append(known, a)
|
||||
i++
|
||||
if i < len(args) {
|
||||
known = append(known, args[i])
|
||||
}
|
||||
default:
|
||||
if knownArg(a) {
|
||||
known = append(known, a)
|
||||
|
|
|
|||
|
|
@ -36,10 +36,15 @@ This command packages a chart into a versioned chart archive file. If a path
|
|||
is given, this will look at that path for a chart (which must contain a
|
||||
Chart.yaml file) and then package that directory.
|
||||
|
||||
If no path is given, this will look in the present working directory for a
|
||||
Chart.yaml file, and (if found) build the current directory into a chart.
|
||||
|
||||
Versioned chart archives are used by Helm package repositories.
|
||||
|
||||
To sign a chart, use the '--sign' flag. In most cases, you should also
|
||||
provide '--keyring path/to/secret/keys' and '--key keyname'.
|
||||
|
||||
$ helm package --sign ./mychart --key mykey --keyring ~/.gnupg/secring.gpg
|
||||
|
||||
If '--keyring' is not specified, Helm usually defaults to the public keyring
|
||||
unless your environment is otherwise configured.
|
||||
`
|
||||
|
||||
func newPackageCmd(out io.Writer) *cobra.Command {
|
||||
|
|
|
|||
|
|
@ -30,14 +30,27 @@ func TestManuallyProcessArgs(t *testing.T) {
|
|||
"--debug",
|
||||
"--foo", "bar",
|
||||
"--kubeconfig=/home/foo",
|
||||
"--kubeconfig", "/home/foo",
|
||||
"--kube-context=test1",
|
||||
"--kube-context", "test1",
|
||||
"-n=test2",
|
||||
"-n", "test2",
|
||||
"--namespace=test2",
|
||||
"--namespace", "test2",
|
||||
"--home=/tmp",
|
||||
"command",
|
||||
}
|
||||
|
||||
expectKnown := []string{
|
||||
"--debug", "--kubeconfig=/home/foo", "--kube-context", "test1", "-n", "test2",
|
||||
"--debug",
|
||||
"--kubeconfig=/home/foo",
|
||||
"--kubeconfig", "/home/foo",
|
||||
"--kube-context=test1",
|
||||
"--kube-context", "test1",
|
||||
"-n=test2",
|
||||
"-n", "test2",
|
||||
"--namespace=test2",
|
||||
"--namespace", "test2",
|
||||
}
|
||||
|
||||
expectUnknown := []string{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/gofrs/flock"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"helm.sh/helm/v3/cmd/helm/require"
|
||||
"helm.sh/helm/v3/pkg/getter"
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ __helm_override_flags_to_kubectl_flags()
|
|||
# --kubeconfig, -n, --namespace stay the same for kubectl
|
||||
# --kube-context becomes --context for kubectl
|
||||
__helm_debug "${FUNCNAME[0]}: flags to convert: $1"
|
||||
echo "$1" | sed s/kube-context/context/
|
||||
echo "$1" | \sed s/kube-context/context/
|
||||
}
|
||||
|
||||
__helm_get_repos()
|
||||
{
|
||||
eval $(__helm_binary_name) repo list 2>/dev/null | tail +2 | cut -f1
|
||||
eval $(__helm_binary_name) repo list 2>/dev/null | \tail +2 | \cut -f1
|
||||
}
|
||||
|
||||
__helm_get_contexts()
|
||||
|
|
@ -125,7 +125,7 @@ __helm_zsh_comp_nospace() {
|
|||
# We only do this if there is a single choice left for completion
|
||||
# to reduce the times the user could be presented with the fake completion choice.
|
||||
|
||||
out=($(echo ${in[*]} | tr " " "\n" | \grep "^${cur}"))
|
||||
out=($(echo ${in[*]} | \tr " " "\n" | \grep "^${cur}"))
|
||||
__helm_debug "${FUNCNAME[0]}: out is ${out[*]}"
|
||||
|
||||
[ ${#out[*]} -eq 1 ] && out+=("${out}.")
|
||||
|
|
@ -145,7 +145,7 @@ __helm_list_charts()
|
|||
for repo in $(__helm_get_repos); do
|
||||
if [[ "${cur}" =~ ^${repo}/.* ]]; then
|
||||
# We are doing completion from within a repo
|
||||
out=$(eval $(__helm_binary_name) search repo ${cur} 2>/dev/null | cut -f1 | \grep ^${cur})
|
||||
out=$(eval $(__helm_binary_name) search repo ${cur} 2>/dev/null | \cut -f1 | \grep ^${cur})
|
||||
nospace=0
|
||||
elif [[ ${repo} =~ ^${cur}.* ]]; then
|
||||
# We are completing a repo name
|
||||
|
|
@ -236,7 +236,7 @@ __helm_list_plugins()
|
|||
__helm_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
local out
|
||||
# Use eval in case helm_binary_name contains a variable (e.g., $HOME/bin/h3)
|
||||
if out=$(eval $(__helm_binary_name) plugin list 2>/dev/null | tail +2 | cut -f1); then
|
||||
if out=$(eval $(__helm_binary_name) plugin list 2>/dev/null | \tail +2 | \cut -f1); then
|
||||
COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) )
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@ import (
|
|||
"helm.sh/helm/v3/pkg/release"
|
||||
)
|
||||
|
||||
// NOTE: Keep the list of statuses up-to-date with pkg/release/status.go.
|
||||
var statusHelp = `
|
||||
This command shows the status of a named release.
|
||||
The status consists of:
|
||||
- last deployment time
|
||||
- k8s namespace in which the release lives
|
||||
- state of the release (can be: unknown, deployed, deleted, superseded, failed or deleting)
|
||||
- state of the release (can be: unknown, deployed, uninstalled, superseded, failed, uninstalling, pending-install, pending-upgrade or pending-rollback)
|
||||
- list of resources that this release consists of, sorted by kind
|
||||
- details on last test suite run, if applicable
|
||||
- additional notes provided by the chart
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ faked locally. Additionally, none of the server-side testing of chart validity
|
|||
|
||||
func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
||||
var validate bool
|
||||
var includeCrds bool
|
||||
client := action.NewInstall(cfg)
|
||||
valueOpts := &values.Options{}
|
||||
var extraAPIs []string
|
||||
|
|
@ -67,7 +68,14 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
|
||||
var manifests bytes.Buffer
|
||||
|
||||
if includeCrds {
|
||||
for _, f := range rel.Chart.CRDs() {
|
||||
fmt.Fprintf(&manifests, "---\n# Source: %s\n%s\n", f.Name, f.Data)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(&manifests, strings.TrimSpace(rel.Manifest))
|
||||
|
||||
if !client.DisableHooks {
|
||||
for _, m := range rel.Hooks {
|
||||
fmt.Fprintf(&manifests, "---\n# Source: %s\n%s\n", m.Path, m.Manifest)
|
||||
|
|
@ -120,6 +128,8 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.StringArrayVarP(&showFiles, "show-only", "s", []string{}, "only show manifests rendered from the given templates")
|
||||
f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
|
||||
f.BoolVar(&validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. This is the same validation performed on an install")
|
||||
f.BoolVar(&includeCrds, "include-crds", false, "include CRDs in the templated output")
|
||||
f.BoolVar(&client.IsUpgrade, "is-upgrade", false, "set .Release.IsUpgrade instead of .Release.IsInstall")
|
||||
f.StringArrayVarP(&extraAPIs, "api-versions", "a", []string{}, "Kubernetes api versions used for Capabilities.APIVersions")
|
||||
|
||||
return cmd
|
||||
|
|
|
|||
|
|
@ -79,6 +79,11 @@ func TestTemplateCmd(t *testing.T) {
|
|||
cmd: fmt.Sprintf("template --api-versions helm.k8s.io/test '%s'", chartPath),
|
||||
golden: "output/template-with-api-version.txt",
|
||||
},
|
||||
{
|
||||
name: "template with CRDs",
|
||||
cmd: fmt.Sprintf("template '%s' --include-crds", chartPath),
|
||||
golden: "output/template-with-crds.txt",
|
||||
},
|
||||
}
|
||||
runTestCmd(t, tests)
|
||||
}
|
||||
|
|
|
|||
7
cmd/helm/testdata/output/deprecated-chart.txt
vendored
Normal file
7
cmd/helm/testdata/output/deprecated-chart.txt
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
WARNING: This chart is deprecated
|
||||
NAME: aeneas
|
||||
LAST DEPLOYED: Fri Sep 2 22:04:05 1977
|
||||
NAMESPACE: default
|
||||
STATUS: deployed
|
||||
REVISION: 1
|
||||
TEST SUITE: None
|
||||
2
cmd/helm/testdata/output/search-single.txt
vendored
2
cmd/helm/testdata/output/search-single.txt
vendored
|
|
@ -1,2 +0,0 @@
|
|||
NAME CHART VERSION APP VERSION DESCRIPTION
|
||||
testing/mariadb 0.3.0 Chart for MariaDB
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
NAME: flummoxed-chickadee
|
||||
LAST DEPLOYED: 2016-01-16 00:00:00 +0000 UTC
|
||||
NAMESPACE: default
|
||||
STATUS: deployed
|
||||
|
||||
RESOURCES:
|
||||
resource A
|
||||
resource B
|
||||
|
||||
10
cmd/helm/testdata/output/status.yaml
vendored
10
cmd/helm/testdata/output/status.yaml
vendored
|
|
@ -1,10 +0,0 @@
|
|||
info:
|
||||
deleted: "0001-01-01T00:00:00Z"
|
||||
first_deployed: "0001-01-01T00:00:00Z"
|
||||
last_deployed: "2016-01-16T00:00:00Z"
|
||||
resources: |
|
||||
resource A
|
||||
resource B
|
||||
status: deployed
|
||||
name: flummoxed-chickadee
|
||||
namespace: default
|
||||
72
cmd/helm/testdata/output/template-with-crds.txt
vendored
Normal file
72
cmd/helm/testdata/output/template-with-crds.txt
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
# Source: crds/crdA.yaml
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: testCRDs
|
||||
spec:
|
||||
group: testCRDGroups
|
||||
names:
|
||||
kind: TestCRD
|
||||
listKind: TestCRDList
|
||||
plural: TestCRDs
|
||||
shortNames:
|
||||
- tc
|
||||
singular: authconfig
|
||||
|
||||
---
|
||||
# Source: subchart1/charts/subcharta/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subcharta
|
||||
labels:
|
||||
helm.sh/chart: "subcharta-0.1.0"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: apache
|
||||
selector:
|
||||
app.kubernetes.io/name: subcharta
|
||||
---
|
||||
# Source: subchart1/charts/subchartb/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subchartb
|
||||
labels:
|
||||
helm.sh/chart: "subchartb-0.1.0"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: nginx
|
||||
selector:
|
||||
app.kubernetes.io/name: subchartb
|
||||
---
|
||||
# Source: subchart1/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subchart1
|
||||
labels:
|
||||
helm.sh/chart: "subchart1-0.1.0"
|
||||
app.kubernetes.io/instance: "RELEASE-NAME"
|
||||
kube-version/major: "1"
|
||||
kube-version/minor: "16"
|
||||
kube-version/version: "v1.16.0"
|
||||
kube-api-version/test: v1
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: nginx
|
||||
selector:
|
||||
app.kubernetes.io/name: subchart1
|
||||
|
|
@ -1 +1 @@
|
|||
version.BuildInfo{Version:"v3.0+unreleased", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.0", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
|
|
|
|||
2
cmd/helm/testdata/output/version-client.txt
vendored
2
cmd/helm/testdata/output/version-client.txt
vendored
|
|
@ -1 +1 @@
|
|||
version.BuildInfo{Version:"v3.0+unreleased", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.0", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
|
|
|
|||
2
cmd/helm/testdata/output/version-short.txt
vendored
2
cmd/helm/testdata/output/version-short.txt
vendored
|
|
@ -1 +1 @@
|
|||
v3.0+unreleased
|
||||
v3.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Version: v3.0+unreleased
|
||||
Version: v3.0
|
||||
2
cmd/helm/testdata/output/version.txt
vendored
2
cmd/helm/testdata/output/version.txt
vendored
|
|
@ -1 +1 @@
|
|||
version.BuildInfo{Version:"v3.0+unreleased", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.0", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
|
|
|
|||
8
cmd/helm/testdata/testcharts/deprecated/Chart.yaml
vendored
Normal file
8
cmd/helm/testdata/testcharts/deprecated/Chart.yaml
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
apiVersion: v1
|
||||
description: Deprecated testing chart
|
||||
home: https://helm.sh/helm
|
||||
name: deprecated
|
||||
sources:
|
||||
- https://github.com/helm/helm
|
||||
version: 0.1.0
|
||||
deprecated: true
|
||||
3
cmd/helm/testdata/testcharts/deprecated/README.md
vendored
Normal file
3
cmd/helm/testdata/testcharts/deprecated/README.md
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#Deprecated
|
||||
|
||||
This space intentionally left blank.
|
||||
|
|
@ -69,6 +69,7 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during uninstallation")
|
||||
f.BoolVar(&client.KeepHistory, "keep-history", false, "remove all associated resources and mark the release as deleted, but retain the release history")
|
||||
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
|
||||
f.StringVar(&client.Description, "description", "", "add a custom description")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
}
|
||||
}
|
||||
|
||||
if ch.Metadata.Deprecated {
|
||||
fmt.Fprintln(out, "WARNING: This chart is deprecated")
|
||||
}
|
||||
|
||||
rel, err := client.Run(args[0], ch, vals)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "UPGRADE FAILED")
|
||||
|
|
@ -156,6 +160,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.IntVar(&client.MaxHistory, "history-max", 10, "limit the maximum number of revisions saved per release. Use 0 for no limit")
|
||||
f.BoolVar(&client.CleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this upgrade when upgrade fails")
|
||||
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")
|
||||
f.StringVar(&client.Description, "description", "", "add a custom description")
|
||||
addChartPathOptionsFlags(f, &client.ChartPathOptions)
|
||||
addValueOptionsFlags(f, valueOpts)
|
||||
bindOutputFlag(cmd, &outfmt)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# Kubernetes Community Code of Conduct
|
||||
# Community Code of Conduct
|
||||
|
||||
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
||||
Helm follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -5,8 +5,8 @@ go 1.13
|
|||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect
|
||||
github.com/Masterminds/semver/v3 v3.0.1
|
||||
github.com/Masterminds/sprig/v3 v3.0.0
|
||||
github.com/Masterminds/semver/v3 v3.0.3
|
||||
github.com/Masterminds/sprig/v3 v3.0.2
|
||||
github.com/Masterminds/vcs v1.13.0
|
||||
github.com/Microsoft/go-winio v0.4.12 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -27,8 +27,12 @@ github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RP
|
|||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.0.1 h1:2kKm5lb7dKVrt5TYUiAavE6oFc1cFT0057UVGT+JqLk=
|
||||
github.com/Masterminds/semver/v3 v3.0.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14=
|
||||
github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/sprig/v3 v3.0.0 h1:KSQz7Nb08/3VU9E4ns29dDxcczhOD1q7O1UfM4G3t3g=
|
||||
github.com/Masterminds/sprig/v3 v3.0.0/go.mod h1:NEUY/Qq8Gdm2xgYA+NwJM6wmfdRV9xkh8h/Rld20R0U=
|
||||
github.com/Masterminds/sprig/v3 v3.0.2 h1:wz22D0CiSctrliXiI9ZO3HoNApweeRGftyDN+BQa3B8=
|
||||
github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU=
|
||||
github.com/Masterminds/vcs v1.13.0 h1:USF5TvZGYgIpcbNAEMLfFhHqP08tFZVlUVrmTSpqnyA=
|
||||
github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
|
|
|
|||
|
|
@ -27,18 +27,14 @@ import (
|
|||
// Options represents configurable options used to create client and server TLS configurations.
|
||||
type Options struct {
|
||||
CaCertFile string
|
||||
// If either the KeyFile or CertFile is empty, ClientConfig() will not load them,
|
||||
// preventing Helm from authenticating to Tiller. They are required to be non-empty
|
||||
// when calling ServerConfig, otherwise an error is returned.
|
||||
// If either the KeyFile or CertFile is empty, ClientConfig() will not load them.
|
||||
KeyFile string
|
||||
CertFile string
|
||||
// Client-only options
|
||||
InsecureSkipVerify bool
|
||||
// Server-only options
|
||||
ClientAuth tls.ClientAuthType
|
||||
}
|
||||
|
||||
// ClientConfig retusn a TLS configuration for use by a Helm client.
|
||||
// ClientConfig returns a TLS configuration for use by a Helm client.
|
||||
func ClientConfig(opts Options) (cfg *tls.Config, err error) {
|
||||
var cert *tls.Certificate
|
||||
var pool *x509.CertPool
|
||||
|
|
@ -60,24 +56,3 @@ func ClientConfig(opts Options) (cfg *tls.Config, err error) {
|
|||
cfg = &tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify, Certificates: []tls.Certificate{*cert}, RootCAs: pool}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// ServerConfig returns a TLS configuration for use by the Tiller server.
|
||||
func ServerConfig(opts Options) (cfg *tls.Config, err error) {
|
||||
var cert *tls.Certificate
|
||||
var pool *x509.CertPool
|
||||
|
||||
if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errors.Wrapf(err, "could not load x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile)
|
||||
}
|
||||
return nil, errors.Wrapf(err, "could not read x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile)
|
||||
}
|
||||
if opts.ClientAuth >= tls.VerifyClientCertIfGiven && opts.CaCertFile != "" {
|
||||
if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cfg = &tls.Config{MinVersion: tls.VersionTLS12, ClientAuth: opts.ClientAuth, Certificates: []tls.Certificate{*cert}, ClientCAs: pool}
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package tlsutil
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
|
@ -54,26 +53,6 @@ func TestClientConfig(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestServerConfig(t *testing.T) {
|
||||
opts := Options{
|
||||
CaCertFile: testfile(t, testCaCertFile),
|
||||
CertFile: testfile(t, testCertFile),
|
||||
KeyFile: testfile(t, testKeyFile),
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}
|
||||
|
||||
cfg, err := ServerConfig(opts)
|
||||
if err != nil {
|
||||
t.Fatalf("error building tls server config: %v", err)
|
||||
}
|
||||
if got := cfg.MinVersion; got != tls.VersionTLS12 {
|
||||
t.Errorf("expecting TLS version 1.2, got %d", got)
|
||||
}
|
||||
if got := cfg.ClientCAs; got == nil {
|
||||
t.Errorf("expecting non-nil CA pool")
|
||||
}
|
||||
}
|
||||
|
||||
func testfile(t *testing.T, file string) (path string) {
|
||||
var err error
|
||||
if path, err = filepath.Abs(filepath.Join(tlsTestDir, file)); err != nil {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ var (
|
|||
version = "v3.0"
|
||||
|
||||
// metadata is extra build time data
|
||||
metadata = "unreleased"
|
||||
metadata = ""
|
||||
// gitCommit is the git sha1
|
||||
gitCommit = ""
|
||||
// gitTreeState is the state of the git tree
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ func NewGetValues(cfg *Configuration) *GetValues {
|
|||
|
||||
// Run executes 'helm get values' against the given release.
|
||||
func (g *GetValues) Run(name string) (map[string]interface{}, error) {
|
||||
if err := g.cfg.KubeClient.IsReachable(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rel, err := g.cfg.releaseContent(name, g.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ type Install struct {
|
|||
ReleaseName string
|
||||
GenerateName bool
|
||||
NameTemplate string
|
||||
Description string
|
||||
OutputDir string
|
||||
Atomic bool
|
||||
SkipCRDs bool
|
||||
|
|
@ -86,6 +87,8 @@ type Install struct {
|
|||
// APIVersions allows a manual set of supported API Versions to be passed
|
||||
// (for things like templating). These are ignored if ClientOnly is false
|
||||
APIVersions chartutil.VersionSet
|
||||
// Used by helm template to render charts with .Relase.IsUpgrade. Ignored if Dry-Run is false
|
||||
IsUpgrade bool
|
||||
}
|
||||
|
||||
// ChartPathOptions captures common options used for controlling chart paths
|
||||
|
|
@ -197,11 +200,14 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
|||
return nil, err
|
||||
}
|
||||
|
||||
//special case for helm template --is-upgrade
|
||||
isUpgrade := i.IsUpgrade && i.DryRun
|
||||
options := chartutil.ReleaseOptions{
|
||||
Name: i.ReleaseName,
|
||||
Namespace: i.Namespace,
|
||||
Revision: 1,
|
||||
IsInstall: true,
|
||||
IsInstall: !isUpgrade,
|
||||
IsUpgrade: isUpgrade,
|
||||
}
|
||||
valuesToRender, err := chartutil.ToRenderValues(chrt, vals, options, caps)
|
||||
if err != nil {
|
||||
|
|
@ -237,7 +243,7 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
|||
// we'll end up in a state where we will delete those resources upon
|
||||
// deleting the release because the manifest will be pointing at that
|
||||
// resource
|
||||
if !i.ClientOnly {
|
||||
if !i.ClientOnly && !isUpgrade {
|
||||
if err := existingResourceConflict(resources); err != nil {
|
||||
return nil, errors.Wrap(err, "rendered manifests contain a resource that already exists. Unable to continue with install")
|
||||
}
|
||||
|
|
@ -292,7 +298,11 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
|||
}
|
||||
}
|
||||
|
||||
rel.SetStatus(release.StatusDeployed, "Install complete")
|
||||
if len(i.Description) > 0 {
|
||||
rel.SetStatus(release.StatusDeployed, i.Description)
|
||||
} else {
|
||||
rel.SetStatus(release.StatusDeployed, "Install complete")
|
||||
}
|
||||
|
||||
// This is a tricky case. The release has been created, but the result
|
||||
// cannot be recorded. The truest thing to tell the user is that the
|
||||
|
|
@ -301,7 +311,9 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
|||
//
|
||||
// One possible strategy would be to do a timed retry to see if we can get
|
||||
// this stored in the future.
|
||||
i.recordRelease(rel)
|
||||
if err := i.recordRelease(rel); err != nil {
|
||||
i.cfg.Log("failed to record the release: %s", err)
|
||||
}
|
||||
|
||||
return rel, nil
|
||||
}
|
||||
|
|
@ -420,7 +432,7 @@ func (c *Configuration) renderResources(ch *chart.Chart, values chartutil.Values
|
|||
|
||||
if ch.Metadata.KubeVersion != "" {
|
||||
if !chartutil.IsCompatibleRange(ch.Metadata.KubeVersion, caps.KubeVersion.String()) {
|
||||
return hs, b, "", errors.Errorf("chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, caps.KubeVersion.String())
|
||||
return hs, b, "", errors.Errorf("chart requires kubeVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, caps.KubeVersion.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -543,6 +555,10 @@ func (i *Install) NameAndChart(args []string) (string, string, error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
if len(args) > 2 {
|
||||
return args[0], args[1], errors.Errorf("expected at most two arguments, unexpected arguments: %v", strings.Join(args[2:], ", "))
|
||||
}
|
||||
|
||||
if len(args) == 2 {
|
||||
return args[0], args[1], flagsNotSet()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ func TestInstallRelease_KubeVersion(t *testing.T) {
|
|||
vals = map[string]interface{}{}
|
||||
_, err = instAction.Run(buildChart(withKube(">=99.0.0")), vals)
|
||||
is.Error(err)
|
||||
is.Contains(err.Error(), "chart requires kubernetesVersion")
|
||||
is.Contains(err.Error(), "chart requires kubeVersion")
|
||||
}
|
||||
|
||||
func TestInstallRelease_Wait(t *testing.T) {
|
||||
|
|
@ -505,6 +505,14 @@ func TestNameAndChart(t *testing.T) {
|
|||
t.Fatal("expected an error")
|
||||
}
|
||||
is.Equal("must either provide a name or specify --generate-name", err.Error())
|
||||
|
||||
instAction.NameTemplate = ""
|
||||
instAction.ReleaseName = ""
|
||||
_, _, err = instAction.NameAndChart([]string{"foo", chartName, "bar"})
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
is.Equal("expected at most two arguments, unexpected arguments: bar", err.Error())
|
||||
}
|
||||
|
||||
func TestNameAndChartGenerateName(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -237,27 +237,36 @@ func makeMeSomeReleases(store *storage.Storage, t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilterList(t *testing.T) {
|
||||
one := releaseStub()
|
||||
one.Name = "one"
|
||||
one.Namespace = "default"
|
||||
one.Version = 1
|
||||
two := releaseStub()
|
||||
two.Name = "two"
|
||||
two.Namespace = "default"
|
||||
two.Version = 1
|
||||
anotherOldOne := releaseStub()
|
||||
anotherOldOne.Name = "one"
|
||||
anotherOldOne.Namespace = "testing"
|
||||
anotherOldOne.Version = 1
|
||||
anotherOne := releaseStub()
|
||||
anotherOne.Name = "one"
|
||||
anotherOne.Namespace = "testing"
|
||||
anotherOne.Version = 2
|
||||
t.Run("should filter old versions of the same release", func(t *testing.T) {
|
||||
r1 := releaseStub()
|
||||
r1.Name = "r"
|
||||
r1.Version = 1
|
||||
r2 := releaseStub()
|
||||
r2.Name = "r"
|
||||
r2.Version = 2
|
||||
another := releaseStub()
|
||||
another.Name = "another"
|
||||
another.Version = 1
|
||||
|
||||
list := []*release.Release{one, two, anotherOne}
|
||||
expectedFilteredList := []*release.Release{one, two, anotherOne}
|
||||
filteredList := filterList([]*release.Release{r1, r2, another})
|
||||
expectedFilteredList := []*release.Release{r2, another}
|
||||
|
||||
filteredList := filterList(list)
|
||||
assert.ElementsMatch(t, expectedFilteredList, filteredList)
|
||||
})
|
||||
|
||||
assert.ElementsMatch(t, expectedFilteredList, filteredList)
|
||||
t.Run("should not filter out any version across namespaces", func(t *testing.T) {
|
||||
r1 := releaseStub()
|
||||
r1.Name = "r"
|
||||
r1.Namespace = "default"
|
||||
r1.Version = 1
|
||||
r2 := releaseStub()
|
||||
r2.Name = "r"
|
||||
r2.Namespace = "testing"
|
||||
r2.Version = 2
|
||||
|
||||
filteredList := filterList([]*release.Release{r1, r2})
|
||||
expectedFilteredList := []*release.Release{r1, r2}
|
||||
|
||||
assert.ElementsMatch(t, expectedFilteredList, filteredList)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ func (p *Pull) Run(chartRef string) (string, error) {
|
|||
Getters: getter.All(p.Settings),
|
||||
Options: []getter.Option{
|
||||
getter.WithBasicAuth(p.Username, p.Password),
|
||||
getter.WithTLSClientConfig(p.CertFile, p.KeyFile, p.CaFile),
|
||||
},
|
||||
RepositoryConfig: p.Settings.RepositoryConfig,
|
||||
RepositoryCache: p.Settings.RepositoryCache,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ type Uninstall struct {
|
|||
DryRun bool
|
||||
KeepHistory bool
|
||||
Timeout time.Duration
|
||||
Description string
|
||||
}
|
||||
|
||||
// NewUninstall creates a new Uninstall object with the given configuration.
|
||||
|
|
@ -118,7 +119,11 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
|
|||
}
|
||||
|
||||
rel.Info.Status = release.StatusUninstalled
|
||||
rel.Info.Description = "Uninstallation complete"
|
||||
if len(u.Description) > 0 {
|
||||
rel.Info.Description = u.Description
|
||||
} else {
|
||||
rel.Info.Description = "Uninstallation complete"
|
||||
}
|
||||
|
||||
if !u.KeepHistory {
|
||||
u.cfg.Log("purge requested for %s", name)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ type Upgrade struct {
|
|||
Atomic bool
|
||||
CleanupOnFail bool
|
||||
SubNotes bool
|
||||
Description string
|
||||
}
|
||||
|
||||
// NewUpgrade creates a new Upgrade object with the given configuration.
|
||||
|
|
@ -218,7 +219,11 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
|||
|
||||
if u.DryRun {
|
||||
u.cfg.Log("dry run for %s", upgradedRelease.Name)
|
||||
upgradedRelease.Info.Description = "Dry run complete"
|
||||
if len(u.Description) > 0 {
|
||||
upgradedRelease.Info.Description = u.Description
|
||||
} else {
|
||||
upgradedRelease.Info.Description = "Dry run complete"
|
||||
}
|
||||
return upgradedRelease, nil
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +275,11 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
|||
u.cfg.recordRelease(originalRelease)
|
||||
|
||||
upgradedRelease.Info.Status = release.StatusDeployed
|
||||
upgradedRelease.Info.Description = "Upgrade complete"
|
||||
if len(u.Description) > 0 {
|
||||
upgradedRelease.Info.Description = u.Description
|
||||
} else {
|
||||
upgradedRelease.Info.Description = "Upgrade complete"
|
||||
}
|
||||
|
||||
return upgradedRelease, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,12 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
switch hd.Typeflag {
|
||||
// We don't want to process these extension header files.
|
||||
case tar.TypeXGlobalHeader, tar.TypeXHeader:
|
||||
continue
|
||||
}
|
||||
|
||||
// Archive could contain \ if generated on Windows
|
||||
delimiter := "/"
|
||||
if strings.ContainsRune(hd.Name, '\\') {
|
||||
|
|
|
|||
110
pkg/chart/loader/archive_test.go
Normal file
110
pkg/chart/loader/archive_test.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
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 loader
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadArchiveFiles(t *testing.T) {
|
||||
tcs := []struct {
|
||||
name string
|
||||
generate func(w *tar.Writer)
|
||||
check func(t *testing.T, files []*BufferedFile, err error)
|
||||
}{
|
||||
{
|
||||
name: "empty input should return no files",
|
||||
generate: func(w *tar.Writer) {},
|
||||
check: func(t *testing.T, files []*BufferedFile, err error) {
|
||||
if err.Error() != "no files in chart archive" {
|
||||
t.Fatalf(`expected "no files in chart archive", got [%#v]`, err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should ignore files with XGlobalHeader type",
|
||||
generate: func(w *tar.Writer) {
|
||||
// simulate the presence of a `pax_global_header` file like you would get when
|
||||
// processing a GitHub release archive.
|
||||
_ = w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeXGlobalHeader,
|
||||
Name: "pax_global_header",
|
||||
})
|
||||
|
||||
// we need to have at least one file, otherwise we'll get the "no files in chart archive" error
|
||||
_ = w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeReg,
|
||||
Name: "dir/empty",
|
||||
})
|
||||
},
|
||||
check: func(t *testing.T, files []*BufferedFile, err error) {
|
||||
if err != nil {
|
||||
t.Fatalf(`got unwanted error [%#v] for tar file with pax_global_header content`, err)
|
||||
}
|
||||
|
||||
if len(files) != 1 {
|
||||
t.Fatalf(`expected to get one file but got [%v]`, files)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should ignore files with TypeXHeader type",
|
||||
generate: func(w *tar.Writer) {
|
||||
// simulate the presence of a `pax_header` file like you might get when
|
||||
// processing a GitHub release archive.
|
||||
_ = w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeXHeader,
|
||||
Name: "pax_header",
|
||||
})
|
||||
|
||||
// we need to have at least one file, otherwise we'll get the "no files in chart archive" error
|
||||
_ = w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeReg,
|
||||
Name: "dir/empty",
|
||||
})
|
||||
},
|
||||
check: func(t *testing.T, files []*BufferedFile, err error) {
|
||||
if err != nil {
|
||||
t.Fatalf(`got unwanted error [%#v] for tar file with pax_header content`, err)
|
||||
}
|
||||
|
||||
if len(files) != 1 {
|
||||
t.Fatalf(`expected to get one file but got [%v]`, files)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
gzw := gzip.NewWriter(buf)
|
||||
tw := tar.NewWriter(gzw)
|
||||
|
||||
tc.generate(tw)
|
||||
|
||||
_ = tw.Close()
|
||||
_ = gzw.Close()
|
||||
|
||||
files, err := LoadArchiveFiles(buf)
|
||||
tc.check(t, files, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -114,12 +114,18 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
|
|||
if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil {
|
||||
return c, errors.Wrap(err, "cannot load requirements.yaml")
|
||||
}
|
||||
if c.Metadata.APIVersion == chart.APIVersionV1 {
|
||||
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
|
||||
}
|
||||
// Deprecated: requirements.lock is deprecated use Chart.lock.
|
||||
case f.Name == "requirements.lock":
|
||||
c.Lock = new(chart.Lock)
|
||||
if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil {
|
||||
return c, errors.Wrap(err, "cannot load requirements.lock")
|
||||
}
|
||||
if c.Metadata.APIVersion == chart.APIVersionV1 {
|
||||
c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
|
||||
}
|
||||
|
||||
case strings.HasPrefix(f.Name, "templates/"):
|
||||
c.Templates = append(c.Templates, &chart.File{Name: f.Name, Data: f.Data})
|
||||
|
|
|
|||
|
|
@ -42,7 +42,16 @@ func LoadChartfile(filename string) (*chart.Metadata, error) {
|
|||
//
|
||||
// 'filename' should be the complete path and filename ('foo/Chart.yaml')
|
||||
func SaveChartfile(filename string, cf *chart.Metadata) error {
|
||||
// Pull out the dependencies of a v1 Chart, since there's no way
|
||||
// to tell the serialiser to skip a field for just this use case
|
||||
savedDependencies := cf.Dependencies
|
||||
if cf.APIVersion == chart.APIVersionV1 {
|
||||
cf.Dependencies = nil
|
||||
}
|
||||
out, err := yaml.Marshal(cf)
|
||||
if cf.APIVersion == chart.APIVersionV1 {
|
||||
cf.Dependencies = savedDependencies
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,17 @@ func Save(c *chart.Chart, outDir string) (string, error) {
|
|||
func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
|
||||
base := filepath.Join(prefix, c.Name())
|
||||
|
||||
// Pull out the dependencies of a v1 Chart, since there's no way
|
||||
// to tell the serialiser to skip a field for just this use case
|
||||
savedDependencies := c.Metadata.Dependencies
|
||||
if c.Metadata.APIVersion == chart.APIVersionV1 {
|
||||
c.Metadata.Dependencies = nil
|
||||
}
|
||||
// Save Chart.yaml
|
||||
cdata, err := yaml.Marshal(c.Metadata)
|
||||
if c.Metadata.APIVersion == chart.APIVersionV1 {
|
||||
c.Metadata.Dependencies = savedDependencies
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
13
pkg/chartutil/testdata/subpop/charts/subchart1/crds/crdA.yaml
vendored
Normal file
13
pkg/chartutil/testdata/subpop/charts/subchart1/crds/crdA.yaml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: testCRDs
|
||||
spec:
|
||||
group: testCRDGroups
|
||||
names:
|
||||
kind: TestCRD
|
||||
listKind: TestCRDList
|
||||
plural: TestCRDs
|
||||
shortNames:
|
||||
- tc
|
||||
singular: authconfig
|
||||
|
|
@ -214,6 +214,10 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er
|
|||
c.Options = append(c.Options, getter.WithBasicAuth(r.Config.Username, r.Config.Password))
|
||||
}
|
||||
|
||||
if r.Config.CertFile != "" || r.Config.KeyFile != "" || r.Config.CAFile != "" {
|
||||
c.Options = append(c.Options, getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile))
|
||||
}
|
||||
|
||||
// Next, we need to load the index, and actually look up the chart.
|
||||
idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name))
|
||||
i, err := repo.LoadIndexFile(idxFile)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,67 @@ func TestResolveChartRef(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestResolveChartOpts(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, ref, version string
|
||||
expect []getter.Option
|
||||
}{
|
||||
{
|
||||
name: "repo with CA-file",
|
||||
ref: "testing-ca-file/foo",
|
||||
expect: []getter.Option{
|
||||
getter.WithURL("https://example.com/foo-1.2.3.tgz"),
|
||||
getter.WithTLSClientConfig("cert", "key", "ca"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
c := ChartDownloader{
|
||||
Out: os.Stderr,
|
||||
RepositoryConfig: repoConfig,
|
||||
RepositoryCache: repoCache,
|
||||
Getters: getter.All(&cli.EnvSettings{
|
||||
RepositoryConfig: repoConfig,
|
||||
RepositoryCache: repoCache,
|
||||
}),
|
||||
}
|
||||
|
||||
// snapshot options
|
||||
snapshotOpts := c.Options
|
||||
|
||||
for _, tt := range tests {
|
||||
// reset chart downloader options for each test case
|
||||
c.Options = snapshotOpts
|
||||
|
||||
expect, err := getter.NewHTTPGetter(tt.expect...)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to setup http client: %s", tt.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
u, err := c.ResolveChartVersion(tt.ref, tt.version)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed with error %s", tt.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
got, err := getter.NewHTTPGetter(
|
||||
append(
|
||||
c.Options,
|
||||
getter.WithURL(u.String()),
|
||||
)...,
|
||||
)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to create http client: %s", tt.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if *(got.(*getter.HTTPGetter)) != *(expect.(*getter.HTTPGetter)) {
|
||||
t.Errorf("%s: expected %s, got %s", tt.name, expect, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyChart(t *testing.T) {
|
||||
v, err := VerifyChart("testdata/signtest-0.1.0.tgz", "testdata/helm-test-key.pub")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -149,6 +149,13 @@ func (m *Manager) Update() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// downloadAll might overwrite dependency version, recalculate lock digest
|
||||
newDigest, err := resolver.HashReq(req, lock.Dependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lock.Digest = newDigest
|
||||
|
||||
// If the lock file hasn't changed, don't write a new one.
|
||||
oldLock := c.Lock
|
||||
if oldLock != nil && oldLock.Digest == lock.Digest {
|
||||
|
|
@ -156,7 +163,7 @@ func (m *Manager) Update() error {
|
|||
}
|
||||
|
||||
// Finally, we need to write the lockfile.
|
||||
return writeLock(m.ChartPath, lock)
|
||||
return writeLock(m.ChartPath, lock, c.Metadata.APIVersion == chart.APIVersionV1)
|
||||
}
|
||||
|
||||
func (m *Manager) loadChartDir() (*chart.Chart, error) {
|
||||
|
|
@ -627,12 +634,16 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err
|
|||
}
|
||||
|
||||
// writeLock writes a lockfile to disk
|
||||
func writeLock(chartpath string, lock *chart.Lock) error {
|
||||
func writeLock(chartpath string, lock *chart.Lock, legacyLockfile bool) error {
|
||||
data, err := yaml.Marshal(lock)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dest := filepath.Join(chartpath, "Chart.lock")
|
||||
lockfileName := "Chart.lock"
|
||||
if legacyLockfile {
|
||||
lockfileName = "requirements.lock"
|
||||
}
|
||||
dest := filepath.Join(chartpath, lockfileName)
|
||||
return ioutil.WriteFile(dest, data, 0644)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,74 @@ func TestGetRepoNames(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUpdateBeforeBuild(t *testing.T) {
|
||||
// Set up a fake repo
|
||||
srv, err := repotest.NewTempServer("testdata/*.tgz*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer srv.Stop()
|
||||
if err := srv.LinkIndices(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
dir := func(p ...string) string {
|
||||
return filepath.Join(append([]string{srv.Root()}, p...)...)
|
||||
}
|
||||
|
||||
// Save dep
|
||||
d := &chart.Chart{
|
||||
Metadata: &chart.Metadata{
|
||||
Name: "dep-chart",
|
||||
Version: "0.1.0",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
}
|
||||
if err := chartutil.SaveDir(d, dir()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Save a chart
|
||||
c := &chart.Chart{
|
||||
Metadata: &chart.Metadata{
|
||||
Name: "with-dependency",
|
||||
Version: "0.1.0",
|
||||
APIVersion: "v2",
|
||||
Dependencies: []*chart.Dependency{{
|
||||
Name: d.Metadata.Name,
|
||||
Version: ">=0.1.0",
|
||||
Repository: "file://../dep-chart",
|
||||
}},
|
||||
},
|
||||
}
|
||||
if err := chartutil.SaveDir(c, dir()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Set-up a manager
|
||||
b := bytes.NewBuffer(nil)
|
||||
g := getter.Providers{getter.Provider{
|
||||
Schemes: []string{"http", "https"},
|
||||
New: getter.NewHTTPGetter,
|
||||
}}
|
||||
m := &Manager{
|
||||
ChartPath: dir(c.Metadata.Name),
|
||||
Out: b,
|
||||
Getters: g,
|
||||
RepositoryConfig: dir("repositories.yaml"),
|
||||
RepositoryCache: dir(),
|
||||
}
|
||||
|
||||
// Update before Build. see issue: https://github.com/helm/helm/issues/7101
|
||||
err = m.Update()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = m.Build()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// This function is the skeleton test code of failing tests for #6416 and #6871 and bugs due to #5874.
|
||||
//
|
||||
// This function is used by below tests that ensures success of build operation
|
||||
|
|
@ -217,7 +285,7 @@ func checkBuildWithOptionalFields(t *testing.T, chartName string, dep chart.Depe
|
|||
Metadata: &chart.Metadata{
|
||||
Name: chartName,
|
||||
Version: "0.1.0",
|
||||
APIVersion: "v1",
|
||||
APIVersion: "v2",
|
||||
Dependencies: []*chart.Dependency{&dep},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
7
pkg/downloader/testdata/repositories.yaml
vendored
7
pkg/downloader/testdata/repositories.yaml
vendored
|
|
@ -15,4 +15,9 @@ repositories:
|
|||
- name: testing-relative
|
||||
url: "http://example.com/helm"
|
||||
- name: testing-relative-trailing-slash
|
||||
url: "http://example.com/helm/"
|
||||
url: "http://example.com/helm/"
|
||||
- name: testing-ca-file
|
||||
url: "https://example.com"
|
||||
certFile: "cert"
|
||||
keyFile: "key"
|
||||
caFile: "ca"
|
||||
|
|
|
|||
14
pkg/downloader/testdata/repository/testing-ca-file-index.yaml
vendored
Normal file
14
pkg/downloader/testdata/repository/testing-ca-file-index.yaml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v1
|
||||
entries:
|
||||
foo:
|
||||
- name: foo
|
||||
description: Foo Chart
|
||||
home: https://helm.sh/helm
|
||||
keywords: []
|
||||
maintainers: []
|
||||
sources:
|
||||
- https://github.com/helm/charts
|
||||
urls:
|
||||
- https://example.com/foo-1.2.3.tgz
|
||||
version: 1.2.3
|
||||
checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d
|
||||
|
|
@ -93,11 +93,19 @@ func warnWrap(warn string) string {
|
|||
// initFunMap creates the Engine's FuncMap and adds context-specific functions.
|
||||
func (e Engine) initFunMap(t *template.Template, referenceTpls map[string]renderable) {
|
||||
funcMap := funcMap()
|
||||
includedNames := make([]string, 0)
|
||||
|
||||
// Add the 'include' function here so we can close over t.
|
||||
funcMap["include"] = func(name string, data interface{}) (string, error) {
|
||||
var buf strings.Builder
|
||||
for _, n := range includedNames {
|
||||
if n == name {
|
||||
return "", errors.Wrapf(fmt.Errorf("unable to excute template"), "rendering template has a nested reference name: %s", name)
|
||||
}
|
||||
}
|
||||
includedNames = append(includedNames, name)
|
||||
err := t.ExecuteTemplate(&buf, name, data)
|
||||
includedNames = includedNames[:len(includedNames)-1]
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -460,6 +460,15 @@ func TestAlterFuncMap_include(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
// Check nested reference in include FuncMap
|
||||
d := &chart.Chart{
|
||||
Metadata: &chart.Metadata{Name: "nested"},
|
||||
Templates: []*chart.File{
|
||||
{Name: "templates/quote", Data: []byte(`{{include "nested/templates/quote" . | indent 2}} dead.`)},
|
||||
{Name: "templates/_partial", Data: []byte(`{{.Release.Name}} - he`)},
|
||||
},
|
||||
}
|
||||
|
||||
v := chartutil.Values{
|
||||
"Values": "",
|
||||
"Chart": c.Metadata,
|
||||
|
|
@ -477,6 +486,12 @@ func TestAlterFuncMap_include(t *testing.T) {
|
|||
if got := out["conrad/templates/quote"]; got != expect {
|
||||
t.Errorf("Expected %q, got %q (%v)", expect, got, out)
|
||||
}
|
||||
|
||||
_, err = Render(d, v)
|
||||
expectErrName := "nested/templates/quote"
|
||||
if err == nil {
|
||||
t.Errorf("Expected err of nested reference name: %v", expectErrName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlterFuncMap_require(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import (
|
|||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
|
|
@ -41,6 +42,7 @@ import (
|
|||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
cachetools "k8s.io/client-go/tools/cache"
|
||||
watchtools "k8s.io/client-go/tools/watch"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
|
@ -419,10 +421,13 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err
|
|||
|
||||
c.Log("Watching for changes to %s %s with timeout of %v", kind, info.Name, timeout)
|
||||
|
||||
w, err := resource.NewHelper(info.Client, info.Mapping).WatchSingle(info.Namespace, info.Name, info.ResourceVersion)
|
||||
// Use a selector on the name of the resource. This should be unique for the
|
||||
// given version and kind
|
||||
selector, err := fields.ParseSelector(fmt.Sprintf("metadata.name=%s", info.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lw := cachetools.NewListWatchFromClient(info.Client, info.Mapping.Resource.Resource, info.Namespace, selector)
|
||||
|
||||
// What we watch for depends on the Kind.
|
||||
// - For a Job, we watch for completion.
|
||||
|
|
@ -432,7 +437,7 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err
|
|||
|
||||
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
_, err = watchtools.UntilWithoutRetry(ctx, w, func(e watch.Event) (bool, error) {
|
||||
_, err = watchtools.ListWatchUntil(ctx, lw, func(e watch.Event) (bool, error) {
|
||||
// Make sure the incoming object is versioned as we use unstructured
|
||||
// objects when we build manifests
|
||||
obj := convertWithMapper(e.Object, info.Mapping)
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ const goodChartDir = "rules/testdata/goodone"
|
|||
|
||||
func TestBadChart(t *testing.T) {
|
||||
m := All(badChartDir, values, namespace, strict).Messages
|
||||
if len(m) != 8 {
|
||||
if len(m) != 7 {
|
||||
t.Errorf("Number of errors %v", len(m))
|
||||
t.Errorf("All didn't fail with expected errors, got %#v", m)
|
||||
}
|
||||
// There should be one INFO, 2 WARNINGs and one ERROR messages, check for them
|
||||
var i, w, e, e2, e3, e4, e5, e6 bool
|
||||
var i, w, e, e2, e3, e4, e5 bool
|
||||
for _, msg := range m {
|
||||
if msg.Severity == support.InfoSev {
|
||||
if strings.Contains(msg.Err.Error(), "icon is recommended") {
|
||||
|
|
@ -59,24 +59,21 @@ func TestBadChart(t *testing.T) {
|
|||
if strings.Contains(msg.Err.Error(), "name is required") {
|
||||
e2 = true
|
||||
}
|
||||
if strings.Contains(msg.Err.Error(), "directory name (badchartfile) and chart name () must be the same") {
|
||||
|
||||
if strings.Contains(msg.Err.Error(), "apiVersion is required. The value must be either \"v1\" or \"v2\"") {
|
||||
e3 = true
|
||||
}
|
||||
|
||||
if strings.Contains(msg.Err.Error(), "apiVersion is required. The value must be either \"v1\" or \"v2\"") {
|
||||
if strings.Contains(msg.Err.Error(), "chart type is not valid in apiVersion") {
|
||||
e4 = true
|
||||
}
|
||||
|
||||
if strings.Contains(msg.Err.Error(), "chart type is not valid in apiVersion") {
|
||||
e5 = true
|
||||
}
|
||||
|
||||
if strings.Contains(msg.Err.Error(), "dependencies are not valid in the Chart file with apiVersion") {
|
||||
e6 = true
|
||||
e5 = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !e || !e2 || !e3 || !e4 || !e5 || !e6 || !w || !i {
|
||||
if !e || !e2 || !e3 || !e4 || !e5 || !w || !i {
|
||||
t.Errorf("Didn't find all the expected errors, got %#v", m)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ func Chartfile(linter *support.Linter) {
|
|||
}
|
||||
|
||||
linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartName(chartFile))
|
||||
linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartNameDirMatch(linter.ChartDir, chartFile))
|
||||
|
||||
// Chart metadata
|
||||
linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartAPIVersion(chartFile))
|
||||
|
|
@ -82,13 +81,6 @@ func validateChartName(cf *chart.Metadata) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateChartNameDirMatch(chartDir string, cf *chart.Metadata) error {
|
||||
if cf.Name != filepath.Base(chartDir) {
|
||||
return errors.Errorf("directory name (%s) and chart name (%s) must be the same", filepath.Base(chartDir), cf.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateChartAPIVersion(cf *chart.Metadata) error {
|
||||
if cf.APIVersion == "" {
|
||||
return errors.New("apiVersion is required. The value must be either \"v1\" or \"v2\"")
|
||||
|
|
|
|||
|
|
@ -30,18 +30,15 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
badChartDir = "testdata/badchartfile"
|
||||
goodChartDir = "testdata/goodone"
|
||||
badChartDir = "testdata/badchartfile"
|
||||
)
|
||||
|
||||
var (
|
||||
badChartFilePath = filepath.Join(badChartDir, "Chart.yaml")
|
||||
goodChartFilePath = filepath.Join(goodChartDir, "Chart.yaml")
|
||||
nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml")
|
||||
)
|
||||
|
||||
var badChart, _ = chartutil.LoadChartfile(badChartFilePath)
|
||||
var goodChart, _ = chartutil.LoadChartfile(goodChartFilePath)
|
||||
|
||||
// Validation functions Test
|
||||
func TestValidateChartYamlNotDirectory(t *testing.T) {
|
||||
|
|
@ -73,24 +70,6 @@ func TestValidateChartName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateChartNameDirMatch(t *testing.T) {
|
||||
err := validateChartNameDirMatch(goodChartDir, goodChart)
|
||||
if err != nil {
|
||||
t.Errorf("validateChartNameDirMatch to return no error, gor a linter error")
|
||||
}
|
||||
// It has not name
|
||||
err = validateChartNameDirMatch(badChartDir, badChart)
|
||||
if err == nil {
|
||||
t.Errorf("validatechartnamedirmatch to return a linter error, got no error")
|
||||
}
|
||||
|
||||
// Wrong path
|
||||
err = validateChartNameDirMatch(badChartDir, goodChart)
|
||||
if err == nil {
|
||||
t.Errorf("validatechartnamedirmatch to return a linter error, got no error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateChartVersion(t *testing.T) {
|
||||
var failTest = []struct {
|
||||
Version string
|
||||
|
|
@ -209,36 +188,32 @@ func TestChartfile(t *testing.T) {
|
|||
Chartfile(&linter)
|
||||
msgs := linter.Messages
|
||||
|
||||
if len(msgs) != 7 {
|
||||
t.Errorf("Expected 7 errors, got %d", len(msgs))
|
||||
if len(msgs) != 6 {
|
||||
t.Errorf("Expected 6 errors, got %d", len(msgs))
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[0].Err.Error(), "name is required") {
|
||||
t.Errorf("Unexpected message 0: %s", msgs[0].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[1].Err.Error(), "directory name (badchartfile) and chart name () must be the same") {
|
||||
if !strings.Contains(msgs[1].Err.Error(), "apiVersion is required. The value must be either \"v1\" or \"v2\"") {
|
||||
t.Errorf("Unexpected message 1: %s", msgs[1].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[2].Err.Error(), "apiVersion is required. The value must be either \"v1\" or \"v2\"") {
|
||||
if !strings.Contains(msgs[2].Err.Error(), "version '0.0.0.0' is not a valid SemVer") {
|
||||
t.Errorf("Unexpected message 2: %s", msgs[2].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[3].Err.Error(), "version '0.0.0.0' is not a valid SemVer") {
|
||||
if !strings.Contains(msgs[3].Err.Error(), "icon is recommended") {
|
||||
t.Errorf("Unexpected message 3: %s", msgs[3].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[4].Err.Error(), "icon is recommended") {
|
||||
if !strings.Contains(msgs[4].Err.Error(), "chart type is not valid in apiVersion") {
|
||||
t.Errorf("Unexpected message 4: %s", msgs[4].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[5].Err.Error(), "chart type is not valid in apiVersion") {
|
||||
if !strings.Contains(msgs[5].Err.Error(), "dependencies are not valid in the Chart file with apiVersion") {
|
||||
t.Errorf("Unexpected message 5: %s", msgs[5].Err)
|
||||
}
|
||||
|
||||
if !strings.Contains(msgs[6].Err.Error(), "dependencies are not valid in the Chart file with apiVersion") {
|
||||
t.Errorf("Unexpected message 6: %s", msgs[6].Err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ func (s *Signatory) DecryptKey(fn PassphraseFetcher) error {
|
|||
if s.Entity == nil {
|
||||
return errors.New("private key not found")
|
||||
} else if s.Entity.PrivateKey == nil {
|
||||
return errors.New("provided key is not a private key")
|
||||
return errors.New("provided key is not a private key. Try providing a keyring with secret keys")
|
||||
}
|
||||
|
||||
// Nothing else to do if key is not encrypted.
|
||||
|
|
@ -203,7 +203,7 @@ func (s *Signatory) ClearSign(chartpath string) (string, error) {
|
|||
if s.Entity == nil {
|
||||
return "", errors.New("private key not found")
|
||||
} else if s.Entity.PrivateKey == nil {
|
||||
return "", errors.New("provided key is not a private key")
|
||||
return "", errors.New("provided key is not a private key. Try providing a keyring with secret keys")
|
||||
}
|
||||
|
||||
if fi, err := os.Stat(chartpath); err != nil {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package release
|
|||
type Status string
|
||||
|
||||
// Describe the status of a release
|
||||
// NOTE: Make sure to update cmd/helm/status.go when adding or modifying any of these statuses.
|
||||
const (
|
||||
// StatusUnknown indicates that a release is in an uncertain state.
|
||||
StatusUnknown Status = "unknown"
|
||||
|
|
|
|||
|
|
@ -27,14 +27,16 @@ find_files() {
|
|||
\( -name '*.go' -o -name '*.sh' \)
|
||||
}
|
||||
|
||||
mapfile -t failed_license_header < <(find_files | xargs grep -L 'Licensed under the Apache License, Version 2.0 (the "License")')
|
||||
# Use "|| :" to ignore the error code when grep returns empty
|
||||
failed_license_header=($(find_files | xargs grep -L 'Licensed under the Apache License, Version 2.0 (the "License")' || :))
|
||||
if (( ${#failed_license_header[@]} > 0 )); then
|
||||
echo "Some source files are missing license headers."
|
||||
printf '%s\n' "${failed_license_header[@]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mapfile -t failed_copyright_header < <(find_files | xargs grep -L 'Copyright The Helm Authors.')
|
||||
# Use "|| :" to ignore the error code when grep returns empty
|
||||
failed_copyright_header=($(find_files | xargs grep -L 'Copyright The Helm Authors.' || :))
|
||||
if (( ${#failed_copyright_header[@]} > 0 )); then
|
||||
echo "Some source files are missing the copyright header."
|
||||
printf '%s\n' "${failed_copyright_header[@]}"
|
||||
|
|
|
|||
Loading…
Reference in a new issue