mirror of
https://github.com/helm/helm.git
synced 2026-05-28 04:35:48 -04:00
Merge remote-tracking branch 'upstream/main' into priorityclassorder
This commit is contained in:
commit
2b9f4991d6
272 changed files with 7092 additions and 2471 deletions
|
|
@ -1,20 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
set -euo pipefail
|
||||
|
||||
curl -sSL https://github.com/golangci/golangci-lint/releases/download/v$GOLANGCI_LINT_VERSION/golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz | tar xz
|
||||
sudo mv golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64/golangci-lint /usr/local/bin/golangci-lint
|
||||
rm -rf golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64
|
||||
|
|
@ -1,43 +1,14 @@
|
|||
---
|
||||
|
||||
# This file can be removed when Helm no longer uses CircleCI on any release
|
||||
# branches. Once CircleCI is turned off this file can be removed.
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
working_directory: ~/helm.sh/helm
|
||||
docker:
|
||||
- image: circleci/golang:1.17
|
||||
|
||||
auth:
|
||||
username: $DOCKER_USER
|
||||
password: $DOCKER_PASS
|
||||
|
||||
environment:
|
||||
GOCACHE: "/tmp/go/cache"
|
||||
GOLANGCI_LINT_VERSION: "1.43.0"
|
||||
- image: cimg/go:1.18
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: install test dependencies
|
||||
command: .circleci/bootstrap.sh
|
||||
- run:
|
||||
name: test style
|
||||
command: make test-style
|
||||
- run:
|
||||
name: test
|
||||
command: make test-coverage
|
||||
- run:
|
||||
name: test build
|
||||
command: make
|
||||
- deploy:
|
||||
name: deploy
|
||||
command: .circleci/deploy.sh
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- build:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
set -euo pipefail
|
||||
|
||||
# Skip on pull request builds
|
||||
if [[ -n "${CIRCLE_PR_NUMBER:-}" ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
: ${AZURE_STORAGE_CONNECTION_STRING:?"AZURE_STORAGE_CONNECTION_STRING environment variable is not set"}
|
||||
: ${AZURE_STORAGE_CONTAINER_NAME:?"AZURE_STORAGE_CONTAINER_NAME environment variable is not set"}
|
||||
|
||||
VERSION=
|
||||
if [[ -n "${CIRCLE_TAG:-}" ]]; then
|
||||
VERSION="${CIRCLE_TAG}"
|
||||
elif [[ "${CIRCLE_BRANCH:-}" == "main" ]]; then
|
||||
VERSION="canary"
|
||||
else
|
||||
echo "Skipping deploy step; this is neither a releasable branch or a tag"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Installing Azure CLI"
|
||||
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ stretch main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
|
||||
curl -L https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add
|
||||
sudo apt install apt-transport-https
|
||||
sudo apt update
|
||||
sudo apt install azure-cli
|
||||
|
||||
|
||||
echo "Building helm binaries"
|
||||
make build-cross
|
||||
make dist checksum VERSION="${VERSION}"
|
||||
|
||||
echo "Pushing binaries to Azure"
|
||||
if [[ "${VERSION}" == "canary" ]]; then
|
||||
az storage blob upload-batch -s _dist/ -d "$AZURE_STORAGE_CONTAINER_NAME" --pattern 'helm-*' --connection-string "$AZURE_STORAGE_CONNECTION_STRING" --overwrite
|
||||
else
|
||||
az storage blob upload-batch -s _dist/ -d "$AZURE_STORAGE_CONTAINER_NAME" --pattern 'helm-*' --connection-string "$AZURE_STORAGE_CONNECTION_STRING"
|
||||
fi
|
||||
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
|
|
@ -4,4 +4,8 @@ updates:
|
|||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "daily"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
name: build-pr
|
||||
name: build-test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release-**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # pin@v3.5.3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # pin@4.0.1
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.20'
|
||||
- name: Install golangci-lint
|
||||
run: |
|
||||
curl -sSLO https://github.com/golangci/golangci-lint/releases/download/v$GOLANGCI_LINT_VERSION/golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz
|
||||
|
|
@ -21,9 +26,11 @@ jobs:
|
|||
sudo mv golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64/golangci-lint /usr/local/bin/golangci-lint
|
||||
rm -rf golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64*
|
||||
env:
|
||||
GOLANGCI_LINT_VERSION: '1.43.0'
|
||||
GOLANGCI_LINT_SHA256: 'f3515cebec926257da703ba0a2b169e4a322c11dc31a8b4656b50a43e48877f4'
|
||||
GOLANGCI_LINT_VERSION: '1.51.2'
|
||||
GOLANGCI_LINT_SHA256: '4de479eb9d9bc29da51aec1834e7c255b333723d38dbd56781c68e5dddc6a90b'
|
||||
- name: Test style
|
||||
run: make test-style
|
||||
- name: Run unit tests
|
||||
run: make test-coverage
|
||||
- name: Test build
|
||||
run: make build
|
||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
|
|
@ -35,11 +35,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # pin@v3.5.3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # pinv2.21.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
|
|
@ -50,7 +50,7 @@ jobs:
|
|||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # pinv2.21.2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
|
@ -64,4 +64,4 @@ jobs:
|
|||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # pinv2.21.2
|
||||
|
|
|
|||
75
.github/workflows/release.yml
vendored
Normal file
75
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
name: release
|
||||
on:
|
||||
create:
|
||||
tags:
|
||||
- v*
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Note the only differences between release and canary-release jobs are:
|
||||
# - only canary passes --overwrite flag
|
||||
# - the VERSION make variable passed to 'make dist checksum' is expected to
|
||||
# be "canary" if the job is triggered by a push to "main" branch. If the
|
||||
# job is triggered by a tag push, VERSION should be the tag ref.
|
||||
jobs:
|
||||
release:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # pin@v3.5.3
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # pin@4.0.1
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Run unit tests
|
||||
run: make test-coverage
|
||||
|
||||
- name: Build Helm Binaries
|
||||
run: |
|
||||
make build-cross
|
||||
make dist checksum VERSION="${{ github.ref_name }}"
|
||||
|
||||
- name: Upload Binaries
|
||||
uses: bacongobbler/azure-blob-storage-upload@50f7d898b7697e864130ea04c303ca38b5751c50 # pin@3.0.0
|
||||
env:
|
||||
AZURE_STORAGE_CONNECTION_STRING: "${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}"
|
||||
AZURE_STORAGE_CONTAINER_NAME: "${{ secrets.AZURE_STORAGE_CONTAINER_NAME }}"
|
||||
with:
|
||||
source_dir: _dist
|
||||
container_name: ${{ secrets.AZURE_STORAGE_CONTAINER_NAME }}
|
||||
connection_string: ${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}
|
||||
extra_args: '--pattern helm-*'
|
||||
|
||||
canary-release:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # pin@v3.5.3
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # pin@4.0.1
|
||||
with:
|
||||
go-version: '1.20'
|
||||
|
||||
- name: Run unit tests
|
||||
run: make test-coverage
|
||||
|
||||
- name: Build Helm Binaries
|
||||
run: |
|
||||
make build-cross
|
||||
make dist checksum VERSION="canary"
|
||||
|
||||
- name: Upload Binaries
|
||||
uses: bacongobbler/azure-blob-storage-upload@50f7d898b7697e864130ea04c303ca38b5751c50 # pin@3.0.0
|
||||
with:
|
||||
source_dir: _dist
|
||||
container_name: ${{ secrets.AZURE_STORAGE_CONTAINER_NAME }}
|
||||
connection_string: ${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}
|
||||
extra_args: '--pattern helm-*'
|
||||
# WARNING: this will overwrite existing blobs in your blob storage
|
||||
overwrite: 'true'
|
||||
2
.github/workflows/stale-issue-bot.yaml
vendored
2
.github/workflows/stale-issue-bot.yaml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.'
|
||||
exempt-issue-labels: 'keep open,v4.x'
|
||||
exempt-issue-labels: 'keep open,v4.x,in progress'
|
||||
days-before-stale: 90
|
||||
days-before-close: 30
|
||||
operations-per-run: 100
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ run:
|
|||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- dupl
|
||||
- gofmt
|
||||
- goimports
|
||||
|
|
@ -14,9 +13,7 @@ linters:
|
|||
- misspell
|
||||
- nakedret
|
||||
- revive
|
||||
- structcheck
|
||||
- unused
|
||||
- varcheck
|
||||
- staticcheck
|
||||
|
||||
linters-settings:
|
||||
|
|
|
|||
25
Makefile
25
Makefile
|
|
@ -18,12 +18,13 @@ ACCEPTANCE_DIR:=../acceptance-testing
|
|||
ACCEPTANCE_RUN_TESTS=.
|
||||
|
||||
# go option
|
||||
PKG := ./...
|
||||
TAGS :=
|
||||
TESTS := .
|
||||
TESTFLAGS :=
|
||||
LDFLAGS := -w -s
|
||||
GOFLAGS :=
|
||||
PKG := ./...
|
||||
TAGS :=
|
||||
TESTS := .
|
||||
TESTFLAGS :=
|
||||
LDFLAGS := -w -s
|
||||
GOFLAGS :=
|
||||
CGO_ENABLED ?= 0
|
||||
|
||||
# Rebuild the binary if any of these files change
|
||||
SRC := $(shell find . -type f -name '*.go' -print) go.mod go.sum
|
||||
|
|
@ -77,7 +78,7 @@ all: build
|
|||
build: $(BINDIR)/$(BINNAME)
|
||||
|
||||
$(BINDIR)/$(BINNAME): $(SRC)
|
||||
GO111MODULE=on go build $(GOFLAGS) -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o '$(BINDIR)'/$(BINNAME) ./cmd/helm
|
||||
GO111MODULE=on CGO_ENABLED=$(CGO_ENABLED) go build $(GOFLAGS) -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o '$(BINDIR)'/$(BINNAME) ./cmd/helm
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# install
|
||||
|
|
@ -149,15 +150,15 @@ gen-test-golden: test-unit
|
|||
# ------------------------------------------------------------------------------
|
||||
# dependencies
|
||||
|
||||
# If go get is run from inside the project directory it will add the dependencies
|
||||
# to the go.mod file. To avoid that we change to a directory without a go.mod file
|
||||
# when downloading the following dependencies
|
||||
# If go install is run from inside the project directory it will add the
|
||||
# dependencies to the go.mod file. To avoid that we change to a directory
|
||||
# without a go.mod file when downloading the following dependencies
|
||||
|
||||
$(GOX):
|
||||
(cd /; GO111MODULE=on go get -u github.com/mitchellh/gox)
|
||||
(cd /; GO111MODULE=on go install github.com/mitchellh/gox@latest)
|
||||
|
||||
$(GOIMPORTS):
|
||||
(cd /; GO111MODULE=on go get -u golang.org/x/tools/cmd/goimports)
|
||||
(cd /; GO111MODULE=on go install golang.org/x/tools/cmd/goimports@latest)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# release
|
||||
|
|
|
|||
10
OWNERS
10
OWNERS
|
|
@ -1,18 +1,19 @@
|
|||
maintainers:
|
||||
- adamreese
|
||||
- bacongobbler
|
||||
- hickeyma
|
||||
- joejulian
|
||||
- jdolitsky
|
||||
- marckhouzam
|
||||
- mattfarina
|
||||
- sabre1041
|
||||
- scottrigby
|
||||
- SlickNik
|
||||
- technosophos
|
||||
triage:
|
||||
- joejulian
|
||||
- yxxhero
|
||||
- zonggen
|
||||
- gjenkins8
|
||||
emeritus:
|
||||
- adamreese
|
||||
- bacongobbler
|
||||
- fibonacci1729
|
||||
- jascott1
|
||||
- michelleN
|
||||
|
|
@ -21,6 +22,7 @@ emeritus:
|
|||
- prydonius
|
||||
- rimusz
|
||||
- seh
|
||||
- SlickNik
|
||||
- thomastaylor312
|
||||
- vaikas-google
|
||||
- viglesiasce
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Helm
|
||||
|
||||
[](https://circleci.com/gh/helm/helm)
|
||||
[](https://github.com/helm/helm/actions?workflow=release)
|
||||
[](https://goreportcard.com/report/github.com/helm/helm)
|
||||
[](https://pkg.go.dev/helm.sh/helm/v3)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/3131)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
|
@ -77,7 +76,7 @@ func TestCreateStarterCmd(t *testing.T) {
|
|||
t.Logf("Created %s", dest)
|
||||
}
|
||||
tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl")
|
||||
if err := ioutil.WriteFile(tplpath, []byte("test"), 0644); err != nil {
|
||||
if err := os.WriteFile(tplpath, []byte("test"), 0644); err != nil {
|
||||
t.Fatalf("Could not write template: %s", err)
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +139,7 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) {
|
|||
t.Logf("Created %s", dest)
|
||||
}
|
||||
tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl")
|
||||
if err := ioutil.WriteFile(tplpath, []byte("test"), 0644); err != nil {
|
||||
if err := os.WriteFile(tplpath, []byte("test"), 0644); err != nil {
|
||||
t.Fatalf("Could not write template: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"helm.sh/helm/v3/cmd/helm/require"
|
||||
)
|
||||
|
|
@ -84,7 +86,7 @@ func (o *docsOptions) run(out io.Writer) error {
|
|||
hdrFunc := func(filename string) string {
|
||||
base := filepath.Base(filename)
|
||||
name := strings.TrimSuffix(base, path.Ext(base))
|
||||
title := strings.Title(strings.Replace(name, "_", " ", -1))
|
||||
title := cases.Title(language.Und, cases.NoLower).String(strings.Replace(name, "_", " ", -1))
|
||||
return fmt.Sprintf("---\ntitle: \"%s\"\n---\n\n", title)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ func addValueOptionsFlags(f *pflag.FlagSet, v *values.Options) {
|
|||
f.StringArrayVar(&v.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
|
||||
f.StringArrayVar(&v.StringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
|
||||
f.StringArrayVar(&v.FileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
|
||||
f.StringArrayVar(&v.JSONValues, "set-json", []string{}, "set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2)")
|
||||
f.StringArrayVar(&v.LiteralValues, "set-literal", []string{}, "set a literal STRING value on the command line")
|
||||
}
|
||||
|
||||
func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
|
||||
|
|
@ -59,6 +61,7 @@ func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) {
|
|||
f.StringVar(&c.CertFile, "cert-file", "", "identify HTTPS client using this SSL certificate file")
|
||||
f.StringVar(&c.KeyFile, "key-file", "", "identify HTTPS client using this SSL key file")
|
||||
f.BoolVar(&c.InsecureSkipTLSverify, "insecure-skip-tls-verify", false, "skip tls certificate checks for the chart download")
|
||||
f.BoolVar(&c.PlainHTTP, "plain-http", false, "use insecure HTTP connections for the chart download")
|
||||
f.StringVar(&c.CaFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
|
||||
f.BoolVar(&c.PassCredentialsAll, "pass-credentials", false, "pass credentials to all domains")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func newGetAllCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
return tpl(template, data, out)
|
||||
}
|
||||
|
||||
return output.Table.Write(out, &statusPrinter{res, true, false})
|
||||
return output.Table.Write(out, &statusPrinter{res, true, false, false})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package main // import "helm.sh/helm/v3/cmd/helm"
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -106,10 +106,10 @@ func loadReleasesInMemory(actionConfig *action.Configuration) {
|
|||
return
|
||||
}
|
||||
|
||||
actionConfig.KubeClient = &kubefake.PrintingKubeClient{Out: ioutil.Discard}
|
||||
actionConfig.KubeClient = &kubefake.PrintingKubeClient{Out: io.Discard}
|
||||
|
||||
for _, path := range filePaths {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to read memory driver data", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
|
@ -60,8 +60,11 @@ func runTestCmd(t *testing.T, tests []cmdTestCase) {
|
|||
}
|
||||
t.Logf("running cmd (attempt %d): %s", i+1, tt.cmd)
|
||||
_, out, err := executeActionCommandC(storage, tt.cmd)
|
||||
if (err != nil) != tt.wantError {
|
||||
t.Errorf("expected error, got '%v'", err)
|
||||
if tt.wantError && err == nil {
|
||||
t.Errorf("expected error, got success with the following output:\n%s", out)
|
||||
}
|
||||
if !tt.wantError && err != nil {
|
||||
t.Errorf("expected no error, got: '%v'", err)
|
||||
}
|
||||
if tt.golden != "" {
|
||||
test.AssertGoldenString(t, out, tt.golden)
|
||||
|
|
@ -89,7 +92,7 @@ func executeActionCommandStdinC(store *storage.Storage, in *os.File, cmd string)
|
|||
|
||||
actionConfig := &action.Configuration{
|
||||
Releases: store,
|
||||
KubeClient: &kubefake.PrintingKubeClient{Out: ioutil.Discard},
|
||||
KubeClient: &kubefake.PrintingKubeClient{Out: io.Discard},
|
||||
Capabilities: chartutil.DefaultCapabilities,
|
||||
Log: func(format string, v ...interface{}) {},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ To override values in a chart, use either the '--values' flag and pass in a file
|
|||
or use the '--set' flag and pass configuration from the command line, to force
|
||||
a string value use '--set-string'. You can use '--set-file' to set individual
|
||||
values from a file when the value itself is too long for the command line
|
||||
or is dynamically generated.
|
||||
or is dynamically generated. You can also use '--set-json' to set json values
|
||||
(scalars/objects/arrays) from the command line.
|
||||
|
||||
$ helm install -f myvalues.yaml myredis ./redis
|
||||
|
||||
|
|
@ -67,6 +68,11 @@ or
|
|||
|
||||
$ helm install --set-file my_script=dothings.sh myredis ./redis
|
||||
|
||||
or
|
||||
|
||||
$ helm install --set-json 'master.sidecars=[{"name":"sidecar","image":"myImage","imagePullPolicy":"Always","ports":[{"name":"portname","containerPort":1234}]}]' myredis ./redis
|
||||
|
||||
|
||||
You can specify the '--values'/'-f' flag multiple times. The priority will be given to the
|
||||
last (right-most) file specified. For example, if both myvalues.yaml and override.yaml
|
||||
contained a key called 'Test', the value set in override.yaml would take precedence:
|
||||
|
|
@ -79,6 +85,13 @@ set for a key called 'foo', the 'newbar' value would take precedence:
|
|||
|
||||
$ helm install --set foo=bar --set foo=newbar myredis ./redis
|
||||
|
||||
Similarly, in the following example 'foo' is set to '["four"]':
|
||||
|
||||
$ helm install --set-json='foo=["one", "two", "three"]' --set-json='foo=["four"]' myredis ./redis
|
||||
|
||||
And in the following example, 'foo' is set to '{"key1":"value1","key2":"bar"}':
|
||||
|
||||
$ helm install --set-json='foo={"key1":"value1","key2":"value2"}' --set-json='foo.key2="bar"' myredis ./redis
|
||||
|
||||
To check the generated manifests of a release without installing the chart,
|
||||
the '--debug' and '--dry-run' flags can be combined.
|
||||
|
|
@ -86,13 +99,14 @@ the '--debug' and '--dry-run' flags can be combined.
|
|||
If --verify is set, the chart MUST have a provenance file, and the provenance
|
||||
file MUST pass all verification steps.
|
||||
|
||||
There are five different ways you can express the chart you want to install:
|
||||
There are six different ways you can express the chart you want to install:
|
||||
|
||||
1. By chart reference: helm install mymaria example/mariadb
|
||||
2. By path to a packaged chart: helm install mynginx ./nginx-1.2.3.tgz
|
||||
3. By path to an unpacked chart directory: helm install mynginx ./nginx
|
||||
4. By absolute URL: helm install mynginx https://example.com/charts/nginx-1.2.3.tgz
|
||||
5. By chart reference and repo url: helm install --repo https://example.com/charts/ mynginx nginx
|
||||
6. By OCI registries: helm install mynginx --version 1.2.3 oci://example.com/charts/nginx
|
||||
|
||||
CHART REFERENCES
|
||||
|
||||
|
|
@ -122,12 +136,25 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
return compInstall(args, toComplete, client)
|
||||
},
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
|
||||
client.InsecureSkipTLSverify, client.PlainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
client.SetRegistryClient(registryClient)
|
||||
|
||||
// This is for the case where "" is specifically passed in as a
|
||||
// value. When there is no value passed in NoOptDefVal will be used
|
||||
// and it is set to client. See addInstallFlags.
|
||||
if client.DryRunOption == "" {
|
||||
client.DryRunOption = "none"
|
||||
}
|
||||
rel, err := runInstall(args, client, valueOpts, out)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "INSTALLATION FAILED")
|
||||
}
|
||||
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false})
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false, false})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +167,14 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
|
||||
func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Install, valueOpts *values.Options) {
|
||||
f.BoolVar(&client.CreateNamespace, "create-namespace", false, "create the release namespace if not present")
|
||||
f.BoolVar(&client.DryRun, "dry-run", false, "simulate an install")
|
||||
// --dry-run options with expected outcome:
|
||||
// - Not set means no dry run and server is contacted.
|
||||
// - Set with no value, a value of client, or a value of true and the server is not contacted
|
||||
// - Set with a value of false, none, or false and the server is contacted
|
||||
// The true/false part is meant to reflect some legacy behavior while none is equal to "".
|
||||
f.StringVar(&client.DryRunOption, "dry-run", "", "simulate an install. If --dry-run is set with no option being specified or as '--dry-run=client', it will not attempt cluster connections. Setting '--dry-run=server' allows attempting cluster connections.")
|
||||
f.Lookup("dry-run").NoOptDefVal = "client"
|
||||
f.BoolVar(&client.Force, "force", false, "force resource updates through a replacement strategy")
|
||||
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install")
|
||||
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)")
|
||||
|
|
@ -155,6 +189,7 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal
|
|||
f.BoolVar(&client.Atomic, "atomic", false, "if set, the installation process deletes the installation on failure. The --wait flag will be set automatically if --atomic is used")
|
||||
f.BoolVar(&client.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed. By default, CRDs are installed if not already present")
|
||||
f.BoolVar(&client.SubNotes, "render-subchart-notes", false, "if set, render subchart notes along with the parent")
|
||||
f.BoolVar(&client.EnableDNS, "enable-dns", false, "enable DNS lookups when rendering templates")
|
||||
addValueOptionsFlags(f, valueOpts)
|
||||
addChartPathOptionsFlags(f, &client.ChartPathOptions)
|
||||
|
||||
|
|
@ -230,6 +265,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options
|
|||
RepositoryConfig: settings.RepositoryConfig,
|
||||
RepositoryCache: settings.RepositoryCache,
|
||||
Debug: settings.Debug,
|
||||
RegistryClient: client.GetRegistryClient(),
|
||||
}
|
||||
if err := man.Update(); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -246,6 +282,11 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options
|
|||
|
||||
client.Namespace = settings.Namespace()
|
||||
|
||||
// Validate DryRunOption member is one of the allowed values
|
||||
if err := validateDryRunOptionFlag(client.DryRunOption); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create context and prepare the handle of SIGTERM
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
|
@ -286,3 +327,19 @@ func compInstall(args []string, toComplete string, client *action.Install) ([]st
|
|||
}
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
func validateDryRunOptionFlag(dryRunOptionFlagValue string) error {
|
||||
// Validate dry-run flag value with a set of allowed value
|
||||
allowedDryRunValues := []string{"false", "true", "none", "client", "server"}
|
||||
isAllowed := false
|
||||
for _, v := range allowedDryRunValues {
|
||||
if dryRunOptionFlagValue == v {
|
||||
isAllowed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isAllowed {
|
||||
return errors.New("Invalid dry-run flag. Flag must one of the following: false, true, none, client, server")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/cli/values"
|
||||
"helm.sh/helm/v3/pkg/getter"
|
||||
"helm.sh/helm/v3/pkg/lint/support"
|
||||
)
|
||||
|
||||
var longLintHelp = `
|
||||
|
|
@ -76,12 +77,23 @@ func newLintCmd(out io.Writer) *cobra.Command {
|
|||
|
||||
var message strings.Builder
|
||||
failed := 0
|
||||
errorsOrWarnings := 0
|
||||
|
||||
for _, path := range paths {
|
||||
fmt.Fprintf(&message, "==> Linting %s\n", path)
|
||||
|
||||
result := client.Run([]string{path}, vals)
|
||||
|
||||
// If there is no errors/warnings and quiet flag is set
|
||||
// go to the next chart
|
||||
hasWarningsOrErrors := action.HasWarningsOrErrors(result)
|
||||
if hasWarningsOrErrors {
|
||||
errorsOrWarnings++
|
||||
}
|
||||
if client.Quiet && !hasWarningsOrErrors {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(&message, "==> Linting %s\n", path)
|
||||
|
||||
// All the Errors that are generated by a chart
|
||||
// that failed a lint will be included in the
|
||||
// results.Messages so we only need to print
|
||||
|
|
@ -93,7 +105,9 @@ func newLintCmd(out io.Writer) *cobra.Command {
|
|||
}
|
||||
|
||||
for _, msg := range result.Messages {
|
||||
fmt.Fprintf(&message, "%s\n", msg)
|
||||
if !client.Quiet || msg.Severity > support.InfoSev {
|
||||
fmt.Fprintf(&message, "%s\n", msg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(result.Errors) != 0 {
|
||||
|
|
@ -112,7 +126,9 @@ func newLintCmd(out io.Writer) *cobra.Command {
|
|||
if failed > 0 {
|
||||
return errors.New(summary)
|
||||
}
|
||||
fmt.Fprintln(out, summary)
|
||||
if !client.Quiet || errorsOrWarnings > 0 {
|
||||
fmt.Fprintln(out, summary)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
@ -120,6 +136,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
|
|||
f := cmd.Flags()
|
||||
f.BoolVar(&client.Strict, "strict", false, "fail on lint warnings")
|
||||
f.BoolVar(&client.WithSubcharts, "with-subcharts", false, "lint dependent charts")
|
||||
f.BoolVar(&client.Quiet, "quiet", false, "print only warnings and errors")
|
||||
addValueOptionsFlags(f, valueOpts)
|
||||
|
||||
return cmd
|
||||
|
|
|
|||
|
|
@ -37,6 +37,32 @@ func TestLintCmdWithSubchartsFlag(t *testing.T) {
|
|||
runTestCmd(t, tests)
|
||||
}
|
||||
|
||||
func TestLintCmdWithQuietFlag(t *testing.T) {
|
||||
testChart1 := "testdata/testcharts/alpine"
|
||||
testChart2 := "testdata/testcharts/chart-bad-requirements"
|
||||
tests := []cmdTestCase{{
|
||||
name: "lint good chart using --quiet flag",
|
||||
cmd: fmt.Sprintf("lint --quiet %s", testChart1),
|
||||
golden: "output/lint-quiet.txt",
|
||||
}, {
|
||||
name: "lint two charts, one with error using --quiet flag",
|
||||
cmd: fmt.Sprintf("lint --quiet %s %s", testChart1, testChart2),
|
||||
golden: "output/lint-quiet-with-error.txt",
|
||||
wantError: true,
|
||||
}, {
|
||||
name: "lint chart with warning using --quiet flag",
|
||||
cmd: "lint --quiet testdata/testcharts/chart-with-only-crds",
|
||||
golden: "output/lint-quiet-with-warning.txt",
|
||||
}, {
|
||||
name: "lint non-existent chart using --quiet flag",
|
||||
cmd: "lint --quiet thischartdoesntexist/",
|
||||
golden: "",
|
||||
wantError: true,
|
||||
}}
|
||||
runTestCmd(t, tests)
|
||||
|
||||
}
|
||||
|
||||
func TestLintFileCompletion(t *testing.T) {
|
||||
checkFileCompletion(t, "lint", true)
|
||||
checkFileCompletion(t, "lint mypath", true) // Multiple paths can be given
|
||||
|
|
|
|||
|
|
@ -83,8 +83,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
}
|
||||
|
||||
if client.Short {
|
||||
|
||||
names := make([]string, 0)
|
||||
names := make([]string, 0, len(results))
|
||||
for _, res := range results {
|
||||
names = append(names, res.Name)
|
||||
}
|
||||
|
|
@ -103,17 +102,16 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
fmt.Fprintln(out, res.Name)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
|
||||
}
|
||||
}
|
||||
|
||||
return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat))
|
||||
return outfmt.Write(out, newReleaseListWriter(results, client.TimeFormat, client.NoHeaders))
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format")
|
||||
f.BoolVarP(&client.NoHeaders, "no-headers", "", false, "don't print headers when using the default output format")
|
||||
f.StringVar(&client.TimeFormat, "time-format", "", `format time using golang time formatter. Example: --time-format "2006-01-02 15:04:05Z0700"`)
|
||||
f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
|
||||
f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
|
||||
|
|
@ -145,10 +143,11 @@ type releaseElement struct {
|
|||
}
|
||||
|
||||
type releaseListWriter struct {
|
||||
releases []releaseElement
|
||||
releases []releaseElement
|
||||
noHeaders bool
|
||||
}
|
||||
|
||||
func newReleaseListWriter(releases []*release.Release, timeFormat string) *releaseListWriter {
|
||||
func newReleaseListWriter(releases []*release.Release, timeFormat string, noHeaders bool) *releaseListWriter {
|
||||
// Initialize the array so no results returns an empty array instead of null
|
||||
elements := make([]releaseElement, 0, len(releases))
|
||||
for _, r := range releases {
|
||||
|
|
@ -173,12 +172,14 @@ func newReleaseListWriter(releases []*release.Release, timeFormat string) *relea
|
|||
|
||||
elements = append(elements, element)
|
||||
}
|
||||
return &releaseListWriter{elements}
|
||||
return &releaseListWriter{elements, noHeaders}
|
||||
}
|
||||
|
||||
func (r *releaseListWriter) WriteTable(out io.Writer) error {
|
||||
table := uitable.New()
|
||||
table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
|
||||
if !r.noHeaders {
|
||||
table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
|
||||
}
|
||||
for _, r := range r.releases {
|
||||
table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,11 @@ func TestListCmd(t *testing.T) {
|
|||
cmd: "list",
|
||||
golden: "output/list.txt",
|
||||
rels: releaseFixture,
|
||||
}, {
|
||||
name: "list without headers",
|
||||
cmd: "list --no-headers",
|
||||
golden: "output/list-no-headers.txt",
|
||||
rels: releaseFixture,
|
||||
}, {
|
||||
name: "list all releases",
|
||||
cmd: "list --all",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -154,7 +153,7 @@ func callPluginExecutable(pluginName string, main string, argv []string, out io.
|
|||
func manuallyProcessArgs(args []string) ([]string, []string) {
|
||||
known := []string{}
|
||||
unknown := []string{}
|
||||
kvargs := []string{"--kube-context", "--namespace", "-n", "--kubeconfig", "--kube-apiserver", "--kube-token", "--kube-as-user", "--kube-as-group", "--kube-ca-file", "--registry-config", "--repository-cache", "--repository-config"}
|
||||
kvargs := []string{"--kube-context", "--namespace", "-n", "--kubeconfig", "--kube-apiserver", "--kube-token", "--kube-as-user", "--kube-as-group", "--kube-ca-file", "--registry-config", "--repository-cache", "--repository-config", "--insecure-skip-tls-verify", "--tls-server-name"}
|
||||
knownArg := func(a string) bool {
|
||||
for _, pre := range kvargs {
|
||||
if strings.HasPrefix(a, pre+"=") {
|
||||
|
|
@ -311,7 +310,7 @@ func addPluginCommands(plugin *plugin.Plugin, baseCmd *cobra.Command, cmds *plug
|
|||
// loadFile takes a yaml file at the given path, parses it and returns a pluginCommand object
|
||||
func loadFile(path string) (*pluginCommand, error) {
|
||||
cmds := new(pluginCommand)
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return cmds, fmt.Errorf("file (%s) not provided by plugin. No plugin auto-completion possible", path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
|
@ -87,7 +86,7 @@ func newPackageCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
|
||||
if client.DependencyUpdate {
|
||||
downloadManager := &downloader.Manager{
|
||||
Out: ioutil.Discard,
|
||||
Out: io.Discard,
|
||||
ChartPath: path,
|
||||
Keyring: client.Keyring,
|
||||
Getters: p,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,13 @@ func newPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
client.Version = ">0.0.0-0"
|
||||
}
|
||||
|
||||
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
|
||||
client.InsecureSkipTLSverify, client.PlainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
client.SetRegistryClient(registryClient)
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
output, err := client.Run(args[i])
|
||||
if err != nil {
|
||||
|
|
@ -80,7 +87,7 @@ func newPullCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.BoolVar(&client.Untar, "untar", false, "if set to true, will untar the chart after downloading it")
|
||||
f.BoolVar(&client.VerifyLater, "prov", false, "fetch the provenance file, but don't perform verification")
|
||||
f.StringVar(&client.UntarDir, "untardir", ".", "if untar is specified, this flag specifies the name of the directory into which the chart is expanded")
|
||||
f.StringVarP(&client.DestDir, "destination", "d", ".", "location to write the chart. If this and tardir are specified, tardir is appended to this")
|
||||
f.StringVarP(&client.DestDir, "destination", "d", ".", "location to write the chart. If this and untardir are specified, untardir is appended to this")
|
||||
addChartPathOptionsFlags(f, &client.ChartPathOptions)
|
||||
|
||||
err := cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,16 @@ If the chart has an associated provenance file,
|
|||
it will also be uploaded.
|
||||
`
|
||||
|
||||
type registryPushOptions struct {
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
insecureSkipTLSverify bool
|
||||
plainHTTP bool
|
||||
}
|
||||
|
||||
func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
||||
client := action.NewPushWithOpts(action.WithPushConfig(cfg))
|
||||
o := ®istryPushOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "push [chart] [remote]",
|
||||
|
|
@ -60,8 +68,18 @@ func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
registryClient, err := newRegistryClient(o.certFile, o.keyFile, o.caFile, o.insecureSkipTLSverify, o.plainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
cfg.RegistryClient = registryClient
|
||||
chartRef := args[0]
|
||||
remote := args[1]
|
||||
client := action.NewPushWithOpts(action.WithPushConfig(cfg),
|
||||
action.WithTLSClientConfig(o.certFile, o.keyFile, o.caFile),
|
||||
action.WithInsecureSkipTLSVerify(o.insecureSkipTLSverify),
|
||||
action.WithPlainHTTP(o.plainHTTP),
|
||||
action.WithPushOptWriter(out))
|
||||
client.Settings = settings
|
||||
output, err := client.Run(chartRef, remote)
|
||||
if err != nil {
|
||||
|
|
@ -72,5 +90,12 @@ func newPushCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVar(&o.certFile, "cert-file", "", "identify registry client using this SSL certificate file")
|
||||
f.StringVar(&o.keyFile, "key-file", "", "identify registry client using this SSL key file")
|
||||
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
|
||||
f.BoolVar(&o.insecureSkipTLSverify, "insecure-skip-tls-verify", false, "skip tls certificate checks for the chart upload")
|
||||
f.BoolVar(&o.plainHTTP, "plain-http", false, "use insecure HTTP connections for the chart upload")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/term" //nolint
|
||||
"github.com/moby/term"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"helm.sh/helm/v3/cmd/helm/require"
|
||||
|
|
@ -36,9 +35,18 @@ const registryLoginDesc = `
|
|||
Authenticate to a remote registry.
|
||||
`
|
||||
|
||||
type registryLoginOptions struct {
|
||||
username string
|
||||
password string
|
||||
passwordFromStdinOpt bool
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
insecure bool
|
||||
}
|
||||
|
||||
func newRegistryLoginCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
||||
var usernameOpt, passwordOpt string
|
||||
var passwordFromStdinOpt, insecureOpt bool
|
||||
o := ®istryLoginOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "login [host]",
|
||||
|
|
@ -49,20 +57,27 @@ func newRegistryLoginCmd(cfg *action.Configuration, out io.Writer) *cobra.Comman
|
|||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
hostname := args[0]
|
||||
|
||||
username, password, err := getUsernamePassword(usernameOpt, passwordOpt, passwordFromStdinOpt)
|
||||
username, password, err := getUsernamePassword(o.username, o.password, o.passwordFromStdinOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return action.NewRegistryLogin(cfg).Run(out, hostname, username, password, insecureOpt)
|
||||
return action.NewRegistryLogin(cfg).Run(out, hostname, username, password,
|
||||
action.WithCertFile(o.certFile),
|
||||
action.WithKeyFile(o.keyFile),
|
||||
action.WithCAFile(o.caFile),
|
||||
action.WithInsecure(o.insecure))
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVarP(&usernameOpt, "username", "u", "", "registry username")
|
||||
f.StringVarP(&passwordOpt, "password", "p", "", "registry password or identity token")
|
||||
f.BoolVarP(&passwordFromStdinOpt, "password-stdin", "", false, "read password or identity token from stdin")
|
||||
f.BoolVarP(&insecureOpt, "insecure", "", false, "allow connections to TLS registry without certs")
|
||||
f.StringVarP(&o.username, "username", "u", "", "registry username")
|
||||
f.StringVarP(&o.password, "password", "p", "", "registry password or identity token")
|
||||
f.BoolVarP(&o.passwordFromStdinOpt, "password-stdin", "", false, "read password or identity token from stdin")
|
||||
f.BoolVarP(&o.insecure, "insecure", "", false, "allow connections to TLS registry without certs")
|
||||
f.StringVar(&o.certFile, "cert-file", "", "identify registry client using this SSL certificate file")
|
||||
f.StringVar(&o.keyFile, "key-file", "", "identify registry client using this SSL key file")
|
||||
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -74,7 +89,7 @@ func getUsernamePassword(usernameOpt string, passwordOpt string, passwordFromStd
|
|||
password := passwordOpt
|
||||
|
||||
if passwordFromStdinOpt {
|
||||
passwordFromStdin, err := ioutil.ReadAll(os.Stdin)
|
||||
passwordFromStdin, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
|
|||
return runErr
|
||||
}
|
||||
|
||||
if err := outfmt.Write(out, &statusPrinter{rel, settings.Debug, false}); err != nil {
|
||||
if err := outfmt.Write(out, &statusPrinter{rel, settings.Debug, false, false}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -134,7 +133,7 @@ func (o *repoAddOptions) run(out io.Writer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(o.repoFile)
|
||||
b, err := os.ReadFile(o.repoFile)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
|
@ -213,7 +212,7 @@ func (o *repoAddOptions) run(out io.Writer) error {
|
|||
|
||||
f.Update(&c)
|
||||
|
||||
if err := f.WriteFile(o.repoFile, 0644); err != nil {
|
||||
if err := f.WriteFile(o.repoFile, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(out, "%q has been added to your repositories\n", o.name)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -102,7 +102,7 @@ func TestRepoAdd(t *testing.T) {
|
|||
}
|
||||
os.Setenv(xdg.CacheHomeEnvVar, rootDir)
|
||||
|
||||
if err := o.run(ioutil.Discard); err != nil {
|
||||
if err := o.run(io.Discard); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
|
@ -126,11 +126,11 @@ func TestRepoAdd(t *testing.T) {
|
|||
|
||||
o.forceUpdate = true
|
||||
|
||||
if err := o.run(ioutil.Discard); err != nil {
|
||||
if err := o.run(io.Discard); err != nil {
|
||||
t.Errorf("Repository was not updated: %s", err)
|
||||
}
|
||||
|
||||
if err := o.run(ioutil.Discard); err != nil {
|
||||
if err := o.run(io.Discard); err != nil {
|
||||
t.Errorf("Duplicate repository name was added")
|
||||
}
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ func TestRepoAddCheckLegalName(t *testing.T) {
|
|||
|
||||
wantErrorMsg := fmt.Sprintf("repository name (%s) contains '/', please specify a different name without '/'", testRepoName)
|
||||
|
||||
if err := o.run(ioutil.Discard); err != nil {
|
||||
if err := o.run(io.Discard); err != nil {
|
||||
if wantErrorMsg != err.Error() {
|
||||
t.Fatalf("Actual error %s, not equal to expected error %s", err, wantErrorMsg)
|
||||
}
|
||||
|
|
@ -211,14 +211,14 @@ func repoAddConcurrent(t *testing.T, testName, repoFile string) {
|
|||
forceUpdate: false,
|
||||
repoFile: repoFile,
|
||||
}
|
||||
if err := o.run(ioutil.Discard); err != nil {
|
||||
if err := o.run(io.Discard); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}(fmt.Sprintf("%s-%d", testName, i))
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
b, err := ioutil.ReadFile(repoFile)
|
||||
b, err := os.ReadFile(repoFile)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ func newRepoListCmd(out io.Writer) *cobra.Command {
|
|||
Args: require.NoArgs,
|
||||
ValidArgsFunction: noCompletions,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
f, err := repo.LoadFile(settings.RepositoryConfig)
|
||||
if isNotExist(err) || (len(f.Repositories) == 0 && !(outfmt == output.JSON || outfmt == output.YAML)) {
|
||||
f, _ := repo.LoadFile(settings.RepositoryConfig)
|
||||
if len(f.Repositories) == 0 && !(outfmt == output.JSON || outfmt == output.YAML) {
|
||||
return errors.New("no repositories to show")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func (o *repoRemoveOptions) run(out io.Writer) error {
|
|||
if !r.Remove(name) {
|
||||
return errors.Errorf("no repo named %q found", name)
|
||||
}
|
||||
if err := r.WriteFile(o.repoFile, 0644); err != nil {
|
||||
if err := r.WriteFile(o.repoFile, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -119,7 +118,7 @@ func TestUpdateCustomCacheCmd(t *testing.T) {
|
|||
repoFile: filepath.Join(ts.Root(), "repositories.yaml"),
|
||||
repoCache: cachePath,
|
||||
}
|
||||
b := ioutil.Discard
|
||||
b := io.Discard
|
||||
if err := o.run(b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ package require
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ func runTestCases(t *testing.T, testCases []testCase) {
|
|||
Args: tc.validateFunc,
|
||||
}
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
err := cmd.Execute()
|
||||
if tc.wantError == "" {
|
||||
|
|
|
|||
|
|
@ -45,28 +45,31 @@ Common actions for Helm:
|
|||
|
||||
Environment variables:
|
||||
|
||||
| Name | Description |
|
||||
|------------------------------------|-----------------------------------------------------------------------------------|
|
||||
| $HELM_CACHE_HOME | set an alternative location for storing cached files. |
|
||||
| $HELM_CONFIG_HOME | set an alternative location for storing Helm configuration. |
|
||||
| $HELM_DATA_HOME | set an alternative location for storing Helm data. |
|
||||
| $HELM_DEBUG | indicate whether or not Helm is running in Debug mode |
|
||||
| $HELM_DRIVER | set the backend storage driver. Values are: configmap, secret, memory, sql. |
|
||||
| $HELM_DRIVER_SQL_CONNECTION_STRING | set the connection string the SQL storage driver should use. |
|
||||
| $HELM_MAX_HISTORY | set the maximum number of helm release history. |
|
||||
| $HELM_NAMESPACE | set the namespace used for the helm operations. |
|
||||
| $HELM_NO_PLUGINS | disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins. |
|
||||
| $HELM_PLUGINS | set the path to the plugins directory |
|
||||
| $HELM_REGISTRY_CONFIG | set the path to the registry config file. |
|
||||
| $HELM_REPOSITORY_CACHE | set the path to the repository cache directory |
|
||||
| $HELM_REPOSITORY_CONFIG | set the path to the repositories file. |
|
||||
| $KUBECONFIG | set an alternative Kubernetes configuration file (default "~/.kube/config") |
|
||||
| $HELM_KUBEAPISERVER | set the Kubernetes API Server Endpoint for authentication |
|
||||
| $HELM_KUBECAFILE | set the Kubernetes certificate authority file. |
|
||||
| $HELM_KUBEASGROUPS | set the Groups to use for impersonation using a comma-separated list. |
|
||||
| $HELM_KUBEASUSER | set the Username to impersonate for the operation. |
|
||||
| $HELM_KUBECONTEXT | set the name of the kubeconfig context. |
|
||||
| $HELM_KUBETOKEN | set the Bearer KubeToken used for authentication. |
|
||||
| Name | Description |
|
||||
|------------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| $HELM_CACHE_HOME | set an alternative location for storing cached files. |
|
||||
| $HELM_CONFIG_HOME | set an alternative location for storing Helm configuration. |
|
||||
| $HELM_DATA_HOME | set an alternative location for storing Helm data. |
|
||||
| $HELM_DEBUG | indicate whether or not Helm is running in Debug mode |
|
||||
| $HELM_DRIVER | set the backend storage driver. Values are: configmap, secret, memory, sql. |
|
||||
| $HELM_DRIVER_SQL_CONNECTION_STRING | set the connection string the SQL storage driver should use. |
|
||||
| $HELM_MAX_HISTORY | set the maximum number of helm release history. |
|
||||
| $HELM_NAMESPACE | set the namespace used for the helm operations. |
|
||||
| $HELM_NO_PLUGINS | disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins. |
|
||||
| $HELM_PLUGINS | set the path to the plugins directory |
|
||||
| $HELM_REGISTRY_CONFIG | set the path to the registry config file. |
|
||||
| $HELM_REPOSITORY_CACHE | set the path to the repository cache directory |
|
||||
| $HELM_REPOSITORY_CONFIG | set the path to the repositories file. |
|
||||
| $KUBECONFIG | set an alternative Kubernetes configuration file (default "~/.kube/config") |
|
||||
| $HELM_KUBEAPISERVER | set the Kubernetes API Server Endpoint for authentication |
|
||||
| $HELM_KUBECAFILE | set the Kubernetes certificate authority file. |
|
||||
| $HELM_KUBEASGROUPS | set the Groups to use for impersonation using a comma-separated list. |
|
||||
| $HELM_KUBEASUSER | set the Username to impersonate for the operation. |
|
||||
| $HELM_KUBECONTEXT | set the name of the kubeconfig context. |
|
||||
| $HELM_KUBETOKEN | set the Bearer KubeToken used for authentication. |
|
||||
| $HELM_KUBEINSECURE_SKIP_TLS_VERIFY | indicate if the Kubernetes API server's certificate validation should be skipped (insecure) |
|
||||
| $HELM_KUBETLS_SERVER_NAME | set the server name used to validate the Kubernetes API server certificate |
|
||||
| $HELM_BURST_LIMIT | set the default burst limit in the case the server contains many CRDs (default 100, -1 to disable)|
|
||||
|
||||
Helm stores cache, configuration, and data based on the following configuration order:
|
||||
|
||||
|
|
@ -149,11 +152,7 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
|
|||
flags.ParseErrorsWhitelist.UnknownFlags = true
|
||||
flags.Parse(args)
|
||||
|
||||
registryClient, err := registry.NewClient(
|
||||
registry.ClientOptDebug(settings.Debug),
|
||||
registry.ClientOptWriter(out),
|
||||
registry.ClientOptCredentialsFile(settings.RegistryConfig),
|
||||
)
|
||||
registryClient, err := newDefaultRegistryClient(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -257,3 +256,48 @@ func checkForExpiredRepos(repofile string) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func newRegistryClient(certFile, keyFile, caFile string, insecureSkipTLSverify, plainHTTP bool) (*registry.Client, error) {
|
||||
if certFile != "" && keyFile != "" || caFile != "" || insecureSkipTLSverify {
|
||||
registryClient, err := newRegistryClientWithTLS(certFile, keyFile, caFile, insecureSkipTLSverify)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryClient, nil
|
||||
}
|
||||
registryClient, err := newDefaultRegistryClient(plainHTTP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryClient, nil
|
||||
}
|
||||
|
||||
func newDefaultRegistryClient(plainHTTP bool) (*registry.Client, error) {
|
||||
opts := []registry.ClientOption{
|
||||
registry.ClientOptDebug(settings.Debug),
|
||||
registry.ClientOptEnableCache(true),
|
||||
registry.ClientOptWriter(os.Stderr),
|
||||
registry.ClientOptCredentialsFile(settings.RegistryConfig),
|
||||
}
|
||||
if plainHTTP {
|
||||
opts = append(opts, registry.ClientOptPlainHTTP())
|
||||
}
|
||||
|
||||
// Create a new registry client
|
||||
registryClient, err := registry.NewClient(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryClient, nil
|
||||
}
|
||||
|
||||
func newRegistryClientWithTLS(certFile, keyFile, caFile string, insecureSkipTLSverify bool) (*registry.Client, error) {
|
||||
// Create a new registry client
|
||||
registryClient, err := registry.NewRegistryClientWithTLS(os.Stderr, certFile, keyFile, caFile, insecureSkipTLSverify,
|
||||
settings.RegistryConfig, settings.Debug,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return registryClient, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The Helm Authors.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The Helm Authors.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*Package search provides client-side repository searching.
|
||||
/*
|
||||
Package search provides client-side repository searching.
|
||||
|
||||
This supports building an in-memory search index based on the contents of
|
||||
multiple repositories, and then using string matching or regular expressions
|
||||
|
|
@ -146,11 +147,10 @@ func (i *Index) SearchLiteral(term string, threshold int) []*Result {
|
|||
term = strings.ToLower(term)
|
||||
buf := []*Result{}
|
||||
for k, v := range i.lines {
|
||||
lk := strings.ToLower(k)
|
||||
lv := strings.ToLower(v)
|
||||
res := strings.Index(lv, term)
|
||||
if score := i.calcScore(res, lv); res != -1 && score < threshold {
|
||||
parts := strings.Split(lk, verSep) // Remove version, if it is there.
|
||||
parts := strings.Split(k, verSep) // Remove version, if it is there.
|
||||
buf = append(buf, &Result{Name: parts[0], Score: score, Chart: i.charts[k]})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,11 +105,11 @@ func loadTestIndex(t *testing.T, all bool) *Index {
|
|||
i := NewIndex()
|
||||
i.AddRepo("testing", &repo.IndexFile{Entries: indexfileEntries}, all)
|
||||
i.AddRepo("ztesting", &repo.IndexFile{Entries: map[string]repo.ChartVersions{
|
||||
"pinta": {
|
||||
"Pinta": {
|
||||
{
|
||||
URLs: []string{"http://example.com/charts/pinta-2.0.0.tgz"},
|
||||
Metadata: &chart.Metadata{
|
||||
Name: "pinta",
|
||||
Name: "Pinta",
|
||||
Version: "2.0.0",
|
||||
Description: "Two ship, version two",
|
||||
},
|
||||
|
|
@ -170,14 +170,14 @@ func TestSearchByName(t *testing.T) {
|
|||
query: "pinta",
|
||||
expect: []*Result{
|
||||
{Name: "testing/pinta"},
|
||||
{Name: "ztesting/pinta"},
|
||||
{Name: "ztesting/Pinta"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "repo-specific search for one result",
|
||||
query: "ztesting/pinta",
|
||||
expect: []*Result{
|
||||
{Name: "ztesting/pinta"},
|
||||
{Name: "ztesting/Pinta"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -199,7 +199,15 @@ func TestSearchByName(t *testing.T) {
|
|||
query: "two",
|
||||
expect: []*Result{
|
||||
{Name: "testing/pinta"},
|
||||
{Name: "ztesting/pinta"},
|
||||
{Name: "ztesting/Pinta"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "search mixedCase and result should be mixedCase too",
|
||||
query: "pinta",
|
||||
expect: []*Result{
|
||||
{Name: "testing/pinta"},
|
||||
{Name: "ztesting/Pinta"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -207,7 +215,7 @@ func TestSearchByName(t *testing.T) {
|
|||
query: "TWO",
|
||||
expect: []*Result{
|
||||
{Name: "testing/pinta"},
|
||||
{Name: "ztesting/pinta"},
|
||||
{Name: "ztesting/Pinta"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -259,7 +258,7 @@ func compListChartsOfRepo(repoName string, prefix string) []string {
|
|||
var charts []string
|
||||
|
||||
path := filepath.Join(settings.RepositoryCache, helmpath.CacheChartsFile(repoName))
|
||||
content, err := ioutil.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
if err == nil {
|
||||
scanner := bufio.NewScanner(bytes.NewReader(content))
|
||||
for scanner.Scan() {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
ValidArgsFunction: validArgsFunc,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.OutputFormat = action.ShowAll
|
||||
err := addRegistryClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := runShow(args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -101,6 +105,10 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
ValidArgsFunction: validArgsFunc,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.OutputFormat = action.ShowValues
|
||||
err := addRegistryClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := runShow(args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -118,6 +126,10 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
ValidArgsFunction: validArgsFunc,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.OutputFormat = action.ShowChart
|
||||
err := addRegistryClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := runShow(args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -135,6 +147,10 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
ValidArgsFunction: validArgsFunc,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.OutputFormat = action.ShowReadme
|
||||
err := addRegistryClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := runShow(args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -152,6 +168,10 @@ func newShowCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
ValidArgsFunction: validArgsFunc,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.OutputFormat = action.ShowCRDs
|
||||
err := addRegistryClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := runShow(args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -204,3 +224,13 @@ func runShow(args []string, client *action.Show) (string, error) {
|
|||
}
|
||||
return client.Run(cp)
|
||||
}
|
||||
|
||||
func addRegistryClient(client *action.Show) error {
|
||||
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
|
||||
client.InsecureSkipTLSverify, client.PlainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
client.SetRegistryClient(registryClient)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,14 @@ func TestShowPreReleaseChart(t *testing.T) {
|
|||
name: "show pre-release chart",
|
||||
args: "test/pre-release-chart",
|
||||
fail: true,
|
||||
expectedErr: "failed to download \"test/pre-release-chart\"",
|
||||
expectedErr: "chart \"pre-release-chart\" matching not found in test index. (try 'helm repo update'): no chart version found for pre-release-chart-",
|
||||
},
|
||||
{
|
||||
name: "show pre-release chart",
|
||||
args: "test/pre-release-chart",
|
||||
fail: true,
|
||||
flags: "--version 1.0.0",
|
||||
expectedErr: "failed to download \"test/pre-release-chart\" at version \"1.0.0\"",
|
||||
expectedErr: "chart \"pre-release-chart\" matching 1.0.0 not found in test index. (try 'helm repo update'): no chart version found for pre-release-chart-1.0.0",
|
||||
},
|
||||
{
|
||||
name: "show pre-release chart with 'devel' flag",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
|
@ -25,6 +26,8 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubectl/pkg/cmd/get"
|
||||
|
||||
"helm.sh/helm/v3/cmd/helm/require"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/chartutil"
|
||||
|
|
@ -41,7 +44,7 @@ The status consists of:
|
|||
- state of the release (can be: unknown, deployed, uninstalled, superseded, failed, uninstalling, pending-install, pending-upgrade or pending-rollback)
|
||||
- revision of the release
|
||||
- description of the release (can be completion message or error message, need to enable --show-desc)
|
||||
- list of resources that this release consists of, sorted by kind
|
||||
- list of resources that this release consists of (need to enable --show-resources)
|
||||
- details on last test suite run, if applicable
|
||||
- additional notes provided by the chart
|
||||
`
|
||||
|
|
@ -62,6 +65,13 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
return compListReleases(toComplete, args, cfg)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// When the output format is a table the resources should be fetched
|
||||
// and displayed as a table. When YAML or JSON the resources will be
|
||||
// returned. This mirrors the handling in kubectl.
|
||||
if outfmt == output.Table {
|
||||
client.ShowResourcesTable = true
|
||||
}
|
||||
rel, err := client.Run(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -70,7 +80,7 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
// strip chart metadata from the output
|
||||
rel.Chart = nil
|
||||
|
||||
return outfmt.Write(out, &statusPrinter{rel, false, client.ShowDescription})
|
||||
return outfmt.Write(out, &statusPrinter{rel, false, client.ShowDescription, client.ShowResources})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +102,8 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
bindOutputFlag(cmd, &outfmt)
|
||||
f.BoolVar(&client.ShowDescription, "show-desc", false, "if set, display the description message of the named release")
|
||||
|
||||
f.BoolVar(&client.ShowResources, "show-resources", false, "if set, display the resources of the named release")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
|
@ -99,6 +111,7 @@ type statusPrinter struct {
|
|||
release *release.Release
|
||||
debug bool
|
||||
showDescription bool
|
||||
showResources bool
|
||||
}
|
||||
|
||||
func (s statusPrinter) WriteJSON(out io.Writer) error {
|
||||
|
|
@ -124,6 +137,33 @@ func (s statusPrinter) WriteTable(out io.Writer) error {
|
|||
fmt.Fprintf(out, "DESCRIPTION: %s\n", s.release.Info.Description)
|
||||
}
|
||||
|
||||
if s.showResources && s.release.Info.Resources != nil && len(s.release.Info.Resources) > 0 {
|
||||
buf := new(bytes.Buffer)
|
||||
printFlags := get.NewHumanPrintFlags()
|
||||
typePrinter, _ := printFlags.ToPrinter("")
|
||||
printer := &get.TablePrinter{Delegate: typePrinter}
|
||||
|
||||
var keys []string
|
||||
for key := range s.release.Info.Resources {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
for _, t := range keys {
|
||||
fmt.Fprintf(buf, "==> %s\n", t)
|
||||
|
||||
vk := s.release.Info.Resources[t]
|
||||
for _, resource := range vk {
|
||||
if err := printer.PrintObj(resource, buf); err != nil {
|
||||
fmt.Fprintf(buf, "failed to print object type %s: %v\n", t, err)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "RESOURCES:\n%s\n", buf.String())
|
||||
}
|
||||
|
||||
executions := executionsByHookEvent(s.release)
|
||||
if tests, ok := executions[release.HookTest]; !ok || len(tests) == 0 {
|
||||
fmt.Fprintln(out, "TEST SUITE: None")
|
||||
|
|
|
|||
|
|
@ -68,6 +68,24 @@ func TestStatusCmd(t *testing.T) {
|
|||
Status: release.StatusDeployed,
|
||||
Notes: "release notes",
|
||||
}),
|
||||
}, {
|
||||
name: "get status of a deployed release with resources",
|
||||
cmd: "status --show-resources flummoxed-chickadee",
|
||||
golden: "output/status-with-resources.txt",
|
||||
rels: releasesMockWithStatus(
|
||||
&release.Info{
|
||||
Status: release.StatusDeployed,
|
||||
},
|
||||
),
|
||||
}, {
|
||||
name: "get status of a deployed release with resources in json",
|
||||
cmd: "status --show-resources flummoxed-chickadee -o json",
|
||||
golden: "output/status-with-resources.json",
|
||||
rels: releasesMockWithStatus(
|
||||
&release.Info{
|
||||
Status: release.StatusDeployed,
|
||||
},
|
||||
),
|
||||
}, {
|
||||
name: "get status of a deployed release with test suite",
|
||||
cmd: "status flummoxed-chickadee",
|
||||
|
|
|
|||
|
|
@ -73,6 +73,19 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
client.KubeVersion = parsedKubeVersion
|
||||
}
|
||||
|
||||
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
|
||||
client.InsecureSkipTLSverify, client.PlainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
client.SetRegistryClient(registryClient)
|
||||
|
||||
// This is for the case where "" is specifically passed in as a
|
||||
// value. When there is no value passed in NoOptDefVal will be used
|
||||
// and it is set to client. See addInstallFlags.
|
||||
if client.DryRunOption == "" {
|
||||
client.DryRunOption = "true"
|
||||
}
|
||||
client.DryRun = true
|
||||
client.ReleaseName = "release-name"
|
||||
client.Replace = true // Skip the name check
|
||||
|
|
@ -106,11 +119,15 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
if client.UseReleaseName {
|
||||
newDir = filepath.Join(client.OutputDir, client.ReleaseName)
|
||||
}
|
||||
_, err := os.Stat(filepath.Join(newDir, m.Path))
|
||||
if err == nil {
|
||||
fileWritten[m.Path] = true
|
||||
}
|
||||
|
||||
err = writeToFile(newDir, m.Path, m.Manifest, fileWritten[m.Path])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileWritten[m.Path] = true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -181,7 +198,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.BoolVar(&skipTests, "skip-tests", false, "skip tests from templated output")
|
||||
f.BoolVar(&client.IsUpgrade, "is-upgrade", false, "set .Release.IsUpgrade instead of .Release.IsInstall")
|
||||
f.StringVar(&kubeVersion, "kube-version", "", "Kubernetes version used for Capabilities.KubeVersion")
|
||||
f.StringArrayVarP(&extraAPIs, "api-versions", "a", []string{}, "Kubernetes api versions used for Capabilities.APIVersions")
|
||||
f.StringSliceVarP(&extraAPIs, "api-versions", "a", []string{}, "Kubernetes api versions used for Capabilities.APIVersions")
|
||||
f.BoolVar(&client.UseReleaseName, "release-name", false, "use release name in the output-dir path.")
|
||||
bindPostRenderFlag(cmd, &client.PostRenderer)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import (
|
|||
var chartPath = "testdata/testcharts/subchart"
|
||||
|
||||
func TestTemplateCmd(t *testing.T) {
|
||||
deletevalchart := "testdata/testcharts/issue-9027"
|
||||
|
||||
tests := []cmdTestCase{
|
||||
{
|
||||
name: "check name",
|
||||
|
|
@ -131,6 +133,34 @@ func TestTemplateCmd(t *testing.T) {
|
|||
cmd: fmt.Sprintf(`template '%s' --skip-tests`, chartPath),
|
||||
golden: "output/template-skip-tests.txt",
|
||||
},
|
||||
{
|
||||
// This test case is to ensure the case where specified dependencies
|
||||
// in the Chart.yaml and those where the Chart.yaml don't have them
|
||||
// specified are the same.
|
||||
name: "ensure nil/null values pass to subcharts delete values",
|
||||
cmd: fmt.Sprintf("template '%s'", deletevalchart),
|
||||
golden: "output/issue-9027.txt",
|
||||
},
|
||||
{
|
||||
// Ensure that imported values take precedence over parent chart values
|
||||
name: "template with imported subchart values ensuring import",
|
||||
cmd: fmt.Sprintf("template '%s' --set configmap.enabled=true --set subchartb.enabled=true", chartPath),
|
||||
golden: "output/template-subchart-cm.txt",
|
||||
},
|
||||
{
|
||||
// Ensure that user input values take precedence over imported
|
||||
// values from sub-charts.
|
||||
name: "template with imported subchart values set with --set",
|
||||
cmd: fmt.Sprintf("template '%s' --set configmap.enabled=true --set subchartb.enabled=true --set configmap.value=baz", chartPath),
|
||||
golden: "output/template-subchart-cm-set.txt",
|
||||
},
|
||||
{
|
||||
// Ensure that user input values take precedence over imported
|
||||
// values from sub-charts when passed by file
|
||||
name: "template with imported subchart values set with --set",
|
||||
cmd: fmt.Sprintf("template '%s' -f %s/extra_values.yaml", chartPath, chartPath),
|
||||
golden: "output/template-subchart-cm-set-file.txt",
|
||||
},
|
||||
}
|
||||
runTestCmd(t, tests)
|
||||
}
|
||||
|
|
|
|||
3
cmd/helm/testdata/output/env-comp.txt
vendored
3
cmd/helm/testdata/output/env-comp.txt
vendored
|
|
@ -1,4 +1,5 @@
|
|||
HELM_BIN
|
||||
HELM_BURST_LIMIT
|
||||
HELM_CACHE_HOME
|
||||
HELM_CONFIG_HOME
|
||||
HELM_DATA_HOME
|
||||
|
|
@ -8,6 +9,8 @@ HELM_KUBEASGROUPS
|
|||
HELM_KUBEASUSER
|
||||
HELM_KUBECAFILE
|
||||
HELM_KUBECONTEXT
|
||||
HELM_KUBEINSECURE_SKIP_TLS_VERIFY
|
||||
HELM_KUBETLS_SERVER_NAME
|
||||
HELM_KUBETOKEN
|
||||
HELM_MAX_HISTORY
|
||||
HELM_NAMESPACE
|
||||
|
|
|
|||
32
cmd/helm/testdata/output/issue-9027.txt
vendored
Normal file
32
cmd/helm/testdata/output/issue-9027.txt
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
# Source: issue-9027/charts/subchart/templates/values.yaml
|
||||
global:
|
||||
hash:
|
||||
key3: 13
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
hash:
|
||||
key3: 13
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
---
|
||||
# Source: issue-9027/templates/values.yaml
|
||||
global:
|
||||
hash:
|
||||
key1: null
|
||||
key2: null
|
||||
key3: 13
|
||||
subchart:
|
||||
global:
|
||||
hash:
|
||||
key3: 13
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
hash:
|
||||
key3: 13
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
==> Linting testdata/testcharts/chart-with-bad-subcharts
|
||||
[INFO] Chart.yaml: icon is recommended
|
||||
[WARNING] templates/: directory not found
|
||||
[ERROR] templates/: error unpacking bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required
|
||||
[ERROR] : unable to load chart
|
||||
error unpacking bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required
|
||||
|
||||
|
|
@ -9,12 +9,11 @@
|
|||
[ERROR] Chart.yaml: apiVersion is required. The value must be either "v1" or "v2"
|
||||
[ERROR] Chart.yaml: version is required
|
||||
[INFO] Chart.yaml: icon is recommended
|
||||
[WARNING] templates/: directory not found
|
||||
[ERROR] templates/: validation: chart.metadata.name is required
|
||||
[ERROR] : unable to load chart
|
||||
validation: chart.metadata.name is required
|
||||
|
||||
==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/good-subchart
|
||||
[INFO] Chart.yaml: icon is recommended
|
||||
[WARNING] templates/: directory not found
|
||||
|
||||
Error: 3 chart(s) linted, 2 chart(s) failed
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
==> Linting testdata/testcharts/chart-with-bad-subcharts
|
||||
[INFO] Chart.yaml: icon is recommended
|
||||
[WARNING] templates/: directory not found
|
||||
[ERROR] templates/: error unpacking bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required
|
||||
[ERROR] : unable to load chart
|
||||
error unpacking bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required
|
||||
|
||||
|
|
|
|||
8
cmd/helm/testdata/output/lint-quiet-with-error.txt
vendored
Normal file
8
cmd/helm/testdata/output/lint-quiet-with-error.txt
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
==> Linting testdata/testcharts/chart-bad-requirements
|
||||
[ERROR] Chart.yaml: unable to parse YAML
|
||||
error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator
|
||||
[ERROR] templates/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator
|
||||
[ERROR] : unable to load chart
|
||||
cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator
|
||||
|
||||
Error: 2 chart(s) linted, 1 chart(s) failed
|
||||
0
cmd/helm/testdata/output/lint-quiet-with-warning.txt
vendored
Normal file
0
cmd/helm/testdata/output/lint-quiet-with-warning.txt
vendored
Normal file
0
cmd/helm/testdata/output/lint-quiet.txt
vendored
Normal file
0
cmd/helm/testdata/output/lint-quiet.txt
vendored
Normal file
4
cmd/helm/testdata/output/list-no-headers.txt
vendored
Normal file
4
cmd/helm/testdata/output/list-no-headers.txt
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0 0.0.1
|
||||
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0 0.0.1
|
||||
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0 0.0.1
|
||||
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0 0.0.1
|
||||
1
cmd/helm/testdata/output/status-with-resources.json
vendored
Normal file
1
cmd/helm/testdata/output/status-with-resources.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name":"flummoxed-chickadee","info":{"first_deployed":"","last_deployed":"2016-01-16T00:00:00Z","deleted":"","status":"deployed"},"namespace":"default"}
|
||||
6
cmd/helm/testdata/output/status-with-resources.txt
vendored
Normal file
6
cmd/helm/testdata/output/status-with-resources.txt
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
NAME: flummoxed-chickadee
|
||||
LAST DEPLOYED: Sat Jan 16 00:00:00 2016
|
||||
NAMESPACE: default
|
||||
STATUS: deployed
|
||||
REVISION: 0
|
||||
TEST SUITE: None
|
||||
122
cmd/helm/testdata/output/template-subchart-cm-set-file.txt
vendored
Normal file
122
cmd/helm/testdata/output/template-subchart-cm-set-file.txt
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
# Source: subchart/templates/subdir/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: subchart-sa
|
||||
---
|
||||
# Source: subchart/templates/subdir/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: subchart-cm
|
||||
data:
|
||||
value: qux
|
||||
---
|
||||
# Source: subchart/templates/subdir/role.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: subchart-role
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get","list","watch"]
|
||||
---
|
||||
# Source: subchart/templates/subdir/rolebinding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: subchart-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: subchart-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: subchart-sa
|
||||
namespace: default
|
||||
---
|
||||
# Source: subchart/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: subchart/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: subchart/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subchart
|
||||
labels:
|
||||
helm.sh/chart: "subchart-0.1.0"
|
||||
app.kubernetes.io/instance: "release-name"
|
||||
kube-version/major: "1"
|
||||
kube-version/minor: "20"
|
||||
kube-version/version: "v1.20.0"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: nginx
|
||||
selector:
|
||||
app.kubernetes.io/name: subchart
|
||||
---
|
||||
# Source: subchart/templates/tests/test-config.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "release-name-testconfig"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
data:
|
||||
message: Hello World
|
||||
---
|
||||
# Source: subchart/templates/tests/test-nothing.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "release-name-test"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: "alpine:latest"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: "release-name-testconfig"
|
||||
command:
|
||||
- echo
|
||||
- "$message"
|
||||
restartPolicy: Never
|
||||
122
cmd/helm/testdata/output/template-subchart-cm-set.txt
vendored
Normal file
122
cmd/helm/testdata/output/template-subchart-cm-set.txt
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
# Source: subchart/templates/subdir/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: subchart-sa
|
||||
---
|
||||
# Source: subchart/templates/subdir/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: subchart-cm
|
||||
data:
|
||||
value: baz
|
||||
---
|
||||
# Source: subchart/templates/subdir/role.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: subchart-role
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get","list","watch"]
|
||||
---
|
||||
# Source: subchart/templates/subdir/rolebinding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: subchart-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: subchart-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: subchart-sa
|
||||
namespace: default
|
||||
---
|
||||
# Source: subchart/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: subchart/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: subchart/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subchart
|
||||
labels:
|
||||
helm.sh/chart: "subchart-0.1.0"
|
||||
app.kubernetes.io/instance: "release-name"
|
||||
kube-version/major: "1"
|
||||
kube-version/minor: "20"
|
||||
kube-version/version: "v1.20.0"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: nginx
|
||||
selector:
|
||||
app.kubernetes.io/name: subchart
|
||||
---
|
||||
# Source: subchart/templates/tests/test-config.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "release-name-testconfig"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
data:
|
||||
message: Hello World
|
||||
---
|
||||
# Source: subchart/templates/tests/test-nothing.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "release-name-test"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: "alpine:latest"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: "release-name-testconfig"
|
||||
command:
|
||||
- echo
|
||||
- "$message"
|
||||
restartPolicy: Never
|
||||
122
cmd/helm/testdata/output/template-subchart-cm.txt
vendored
Normal file
122
cmd/helm/testdata/output/template-subchart-cm.txt
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
# Source: subchart/templates/subdir/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: subchart-sa
|
||||
---
|
||||
# Source: subchart/templates/subdir/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: subchart-cm
|
||||
data:
|
||||
value: bar
|
||||
---
|
||||
# Source: subchart/templates/subdir/role.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: subchart-role
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get","list","watch"]
|
||||
---
|
||||
# Source: subchart/templates/subdir/rolebinding.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: subchart-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: subchart-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: subchart-sa
|
||||
namespace: default
|
||||
---
|
||||
# Source: subchart/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: subchart/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: subchart/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: subchart
|
||||
labels:
|
||||
helm.sh/chart: "subchart-0.1.0"
|
||||
app.kubernetes.io/instance: "release-name"
|
||||
kube-version/major: "1"
|
||||
kube-version/minor: "20"
|
||||
kube-version/version: "v1.20.0"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: nginx
|
||||
selector:
|
||||
app.kubernetes.io/name: subchart
|
||||
---
|
||||
# Source: subchart/templates/tests/test-config.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "release-name-testconfig"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
data:
|
||||
message: Hello World
|
||||
---
|
||||
# Source: subchart/templates/tests/test-nothing.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "release-name-test"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: test
|
||||
image: "alpine:latest"
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: "release-name-testconfig"
|
||||
command:
|
||||
- echo
|
||||
- "$message"
|
||||
restartPolicy: Never
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
# Source: crds/crdA.yaml
|
||||
# Source: subchart/crds/crdA.yaml
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
version.BuildInfo{Version:"v3.8", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.12", 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.8", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.12", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
|
|
|
|||
2
cmd/helm/testdata/output/version-short.txt
vendored
2
cmd/helm/testdata/output/version-short.txt
vendored
|
|
@ -1 +1 @@
|
|||
v3.8
|
||||
v3.12
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Version: v3.8
|
||||
Version: v3.12
|
||||
2
cmd/helm/testdata/output/version.txt
vendored
2
cmd/helm/testdata/output/version.txt
vendored
|
|
@ -1 +1 @@
|
|||
version.BuildInfo{Version:"v3.8", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
version.BuildInfo{Version:"v3.12", GitCommit:"", GitTreeState:"", GoVersion:""}
|
||||
|
|
|
|||
6
cmd/helm/testdata/testcharts/issue-9027/Chart.yaml
vendored
Normal file
6
cmd/helm/testdata/testcharts/issue-9027/Chart.yaml
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v2
|
||||
name: issue-9027
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: subchart
|
||||
version: 0.1.0
|
||||
3
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/Chart.yaml
vendored
Normal file
3
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/Chart.yaml
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
apiVersion: v2
|
||||
name: subchart
|
||||
version: 0.1.0
|
||||
1
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/templates/values.yaml
vendored
Normal file
1
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/templates/values.yaml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{{ .Values | toYaml }}
|
||||
17
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/values.yaml
vendored
Normal file
17
cmd/helm/testdata/testcharts/issue-9027/charts/subchart/values.yaml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
global:
|
||||
hash:
|
||||
key1: 1
|
||||
key2: 2
|
||||
key3: 3
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
|
||||
|
||||
hash:
|
||||
key1: 1
|
||||
key2: 2
|
||||
key3: 3
|
||||
key4: 4
|
||||
key5: 5
|
||||
key6: 6
|
||||
1
cmd/helm/testdata/testcharts/issue-9027/templates/values.yaml
vendored
Normal file
1
cmd/helm/testdata/testcharts/issue-9027/templates/values.yaml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{{ .Values | toYaml }}
|
||||
11
cmd/helm/testdata/testcharts/issue-9027/values.yaml
vendored
Normal file
11
cmd/helm/testdata/testcharts/issue-9027/values.yaml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
global:
|
||||
hash:
|
||||
key1: null
|
||||
key2: null
|
||||
key3: 13
|
||||
|
||||
subchart:
|
||||
hash:
|
||||
key1: null
|
||||
key2: null
|
||||
key3: 13
|
||||
|
|
@ -29,6 +29,9 @@ dependencies:
|
|||
parent: imported-chartA-B
|
||||
- child: exports.SCBexported2
|
||||
parent: exports.SCBexported2
|
||||
# - child: exports.configmap
|
||||
# parent: configmap
|
||||
- configmap
|
||||
- SCBexported1
|
||||
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ exports:
|
|||
|
||||
SCBexported2:
|
||||
SCBexported2A: "blaster"
|
||||
|
||||
configmap:
|
||||
configmap:
|
||||
value: "bar"
|
||||
|
||||
global:
|
||||
kolla:
|
||||
|
|
|
|||
5
cmd/helm/testdata/testcharts/subchart/extra_values.yaml
vendored
Normal file
5
cmd/helm/testdata/testcharts/subchart/extra_values.yaml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# This file is used to test values passed by file at the command line
|
||||
|
||||
configmap:
|
||||
enabled: true
|
||||
value: "qux"
|
||||
8
cmd/helm/testdata/testcharts/subchart/templates/subdir/configmap.yaml
vendored
Normal file
8
cmd/helm/testdata/testcharts/subchart/templates/subdir/configmap.yaml
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{{ if .Values.configmap.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ .Chart.Name }}-cm
|
||||
data:
|
||||
value: {{ .Values.configmap.value }}
|
||||
{{- end }}
|
||||
|
|
@ -53,3 +53,7 @@ exports:
|
|||
SC1exported2:
|
||||
all:
|
||||
SC1exported3: "SC1expstr"
|
||||
|
||||
configmap:
|
||||
enabled: false
|
||||
value: "foo"
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
return compListReleases(toComplete, args, cfg)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
validationErr := validateCascadeFlag(client)
|
||||
if validationErr != nil {
|
||||
return validationErr
|
||||
}
|
||||
for i := 0; i < len(args); i++ {
|
||||
|
||||
res, err := client.Run(args[i])
|
||||
|
|
@ -72,8 +76,16 @@ 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.BoolVar(&client.Wait, "wait", false, "if set, will wait until all the resources are deleted before returning. It will wait for as long as --timeout")
|
||||
f.StringVar(&client.DeletionPropagation, "cascade", "background", "Must be \"background\", \"orphan\", or \"foreground\". Selects the deletion cascading strategy for the dependents. Defaults to background.")
|
||||
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
|
||||
}
|
||||
|
||||
func validateCascadeFlag(client *action.Uninstall) error {
|
||||
if client.DeletionPropagation != "background" && client.DeletionPropagation != "foreground" && client.DeletionPropagation != "orphan" {
|
||||
return fmt.Errorf("invalid cascade value (%s). Must be \"background\", \"foreground\", or \"orphan\"", client.DeletionPropagation)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ To override values in a chart, use either the '--values' flag and pass in a file
|
|||
or use the '--set' flag and pass configuration from the command line, to force string
|
||||
values, use '--set-string'. You can use '--set-file' to set individual
|
||||
values from a file when the value itself is too long for the command line
|
||||
or is dynamically generated.
|
||||
or is dynamically generated. You can also use '--set-json' to set json values
|
||||
(scalars/objects/arrays) from the command line.
|
||||
|
||||
You can specify the '--values'/'-f' flag multiple times. The priority will be given to the
|
||||
last (right-most) file specified. For example, if both myvalues.yaml and override.yaml
|
||||
|
|
@ -89,6 +90,19 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client.Namespace = settings.Namespace()
|
||||
|
||||
registryClient, err := newRegistryClient(client.CertFile, client.KeyFile, client.CaFile,
|
||||
client.InsecureSkipTLSverify, client.PlainHTTP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing registry client: %w", err)
|
||||
}
|
||||
client.SetRegistryClient(registryClient)
|
||||
|
||||
// This is for the case where "" is specifically passed in as a
|
||||
// value. When there is no value passed in NoOptDefVal will be used
|
||||
// and it is set to client. See addInstallFlags.
|
||||
if client.DryRunOption == "" {
|
||||
client.DryRunOption = "none"
|
||||
}
|
||||
// Fixes #7002 - Support reading values from STDIN for `upgrade` command
|
||||
// Must load values AFTER determining if we have to call install so that values loaded from stdin are are not read twice
|
||||
if client.Install {
|
||||
|
|
@ -103,7 +117,9 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
instClient := action.NewInstall(cfg)
|
||||
instClient.CreateNamespace = createNamespace
|
||||
instClient.ChartPathOptions = client.ChartPathOptions
|
||||
instClient.Force = client.Force
|
||||
instClient.DryRun = client.DryRun
|
||||
instClient.DryRunOption = client.DryRunOption
|
||||
instClient.DisableHooks = client.DisableHooks
|
||||
instClient.SkipCRDs = client.SkipCRDs
|
||||
instClient.Timeout = client.Timeout
|
||||
|
|
@ -117,12 +133,13 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
instClient.SubNotes = client.SubNotes
|
||||
instClient.Description = client.Description
|
||||
instClient.DependencyUpdate = client.DependencyUpdate
|
||||
instClient.EnableDNS = client.EnableDNS
|
||||
|
||||
rel, err := runInstall(args, instClient, valueOpts, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false})
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false, false})
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -137,6 +154,10 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Validate dry-run flag value is one of the allowed values
|
||||
if err := validateDryRunOptionFlag(client.DryRunOption); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := getter.All(settings)
|
||||
vals, err := valueOpts.MergeValues(p)
|
||||
|
|
@ -204,7 +225,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
fmt.Fprintf(out, "Release %q has been upgraded. Happy Helming!\n", args[0])
|
||||
}
|
||||
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false})
|
||||
return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false, false})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +233,8 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
f.BoolVar(&createNamespace, "create-namespace", false, "if --install is set, create the release namespace if not present")
|
||||
f.BoolVarP(&client.Install, "install", "i", false, "if a release by this name doesn't already exist, run an install")
|
||||
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.DryRun, "dry-run", false, "simulate an upgrade")
|
||||
f.StringVar(&client.DryRunOption, "dry-run", "", "simulate an install. If --dry-run is set with no option being specified or as '--dry-run=client', it will not attempt cluster connections. Setting '--dry-run=server' allows attempting cluster connections.")
|
||||
f.Lookup("dry-run").NoOptDefVal = "client"
|
||||
f.BoolVar(&client.Recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
|
||||
f.MarkDeprecated("recreate-pods", "functionality will no longer be updated. Consult the documentation for other methods to recreate pods")
|
||||
f.BoolVar(&client.Force, "force", false, "force resource updates through a replacement strategy")
|
||||
|
|
@ -230,6 +252,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
|
|||
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")
|
||||
f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "update dependencies if they are missing before installing the chart")
|
||||
f.BoolVar(&client.EnableDNS, "enable-dns", false, "enable DNS lookups when rendering templates")
|
||||
addChartPathOptionsFlags(f, &client.ChartPathOptions)
|
||||
addValueOptionsFlags(f, valueOpts)
|
||||
bindOutputFlag(cmd, &outfmt)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -359,7 +358,7 @@ func TestUpgradeInstallWithValuesFromStdin(t *testing.T) {
|
|||
|
||||
func prepareMockRelease(releaseName string, t *testing.T) (func(n string, v int, ch *chart.Chart) *release.Release, *chart.Chart, string) {
|
||||
tmpChart := ensure.TempDir(t)
|
||||
configmapData, err := ioutil.ReadFile("testdata/testcharts/upgradetest/templates/configmap.yaml")
|
||||
configmapData, err := os.ReadFile("testdata/testcharts/upgradetest/templates/configmap.yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Error loading template yaml %v", err)
|
||||
}
|
||||
|
|
|
|||
189
go.mod
189
go.mod
|
|
@ -1,162 +1,163 @@
|
|||
module helm.sh/helm/v3
|
||||
|
||||
go 1.17
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.0.0
|
||||
github.com/BurntSushi/toml v1.2.1
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/Masterminds/sprig/v3 v3.2.2
|
||||
github.com/Masterminds/squirrel v1.5.2
|
||||
github.com/Masterminds/vcs v1.13.1
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/Masterminds/squirrel v1.5.4
|
||||
github.com/Masterminds/vcs v1.13.3
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535
|
||||
github.com/containerd/containerd v1.5.9
|
||||
github.com/containerd/containerd v1.7.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.3
|
||||
github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684
|
||||
github.com/docker/docker v20.10.13+incompatible
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible
|
||||
github.com/foxcpp/go-mockdns v1.0.0
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/jmoiron/sqlx v1.3.4
|
||||
github.com/lib/pq v1.10.4
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/mitchellh/copystructure v1.2.0
|
||||
github.com/opencontainers/image-spec v1.0.2
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rubenv/sql-migrate v1.1.1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/rubenv/sql-migrate v1.5.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
k8s.io/api v0.23.4
|
||||
k8s.io/apiextensions-apiserver v0.23.4
|
||||
k8s.io/apimachinery v0.23.4
|
||||
k8s.io/apiserver v0.23.4
|
||||
k8s.io/cli-runtime v0.23.4
|
||||
k8s.io/client-go v0.23.4
|
||||
k8s.io/klog/v2 v2.30.0
|
||||
k8s.io/kubectl v0.23.4
|
||||
oras.land/oras-go v1.1.0
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/term v0.10.0
|
||||
golang.org/x/text v0.11.0
|
||||
k8s.io/api v0.27.3
|
||||
k8s.io/apiextensions-apiserver v0.27.3
|
||||
k8s.io/apimachinery v0.27.3
|
||||
k8s.io/apiserver v0.27.3
|
||||
k8s.io/cli-runtime v0.27.3
|
||||
k8s.io/client-go v0.27.3
|
||||
k8s.io/klog/v2 v2.100.1
|
||||
k8s.io/kubectl v0.27.3
|
||||
oras.land/oras-go v1.2.3
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.99.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.20 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.15 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/cli v20.10.11+incompatible // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker v23.0.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.0.2 // indirect
|
||||
github.com/go-logr/logr v1.2.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.1 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/gomodule/redigo v1.8.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/miekg/dns v1.1.25 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.28.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/russross/blackfriday v1.5.2 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/oauth2 v0.4.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect
|
||||
google.golang.org/grpc v1.43.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/component-base v0.23.4 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/component-base v0.27.3 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package fileutil
|
|||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
|
@ -28,7 +27,7 @@ import (
|
|||
// AtomicWriteFile atomically (as atomic as os.Rename allows) writes a file to a
|
||||
// disk.
|
||||
func AtomicWriteFile(filename string, reader io.Reader, mode os.FileMode) error {
|
||||
tempFile, err := ioutil.TempFile(filepath.Split(filename))
|
||||
tempFile, err := os.CreateTemp(filepath.Split(filename))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package fileutil
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
|
@ -37,7 +36,7 @@ func TestAtomicWriteFile(t *testing.T) {
|
|||
t.Errorf("AtomicWriteFile error: %s", err)
|
||||
}
|
||||
|
||||
got, err := ioutil.ReadFile(testpath)
|
||||
got, err := os.ReadFile(testpath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*Package ignore provides tools for writing ignore files (a la .gitignore).
|
||||
/*
|
||||
Package ignore provides tools for writing ignore files (a la .gitignore).
|
||||
|
||||
This provides both an ignore parser and a file-aware processor.
|
||||
|
||||
|
|
@ -23,19 +24,19 @@ format for .gitignore files (https://git-scm.com/docs/gitignore).
|
|||
|
||||
The formatting rules are as follows:
|
||||
|
||||
- Parsing is line-by-line
|
||||
- Empty lines are ignored
|
||||
- Lines the begin with # (comments) will be ignored
|
||||
- Leading and trailing spaces are always ignored
|
||||
- Inline comments are NOT supported ('foo* # Any foo' does not contain a comment)
|
||||
- There is no support for multi-line patterns
|
||||
- Shell glob patterns are supported. See Go's "path/filepath".Match
|
||||
- If a pattern begins with a leading !, the match will be negated.
|
||||
- If a pattern begins with a leading /, only paths relatively rooted will match.
|
||||
- If the pattern ends with a trailing /, only directories will match
|
||||
- If a pattern contains no slashes, file basenames are tested (not paths)
|
||||
- The pattern sequence "**", while legal in a glob, will cause an error here
|
||||
(to indicate incompatibility with .gitignore).
|
||||
- Parsing is line-by-line
|
||||
- Empty lines are ignored
|
||||
- Lines the begin with # (comments) will be ignored
|
||||
- Leading and trailing spaces are always ignored
|
||||
- Inline comments are NOT supported ('foo* # Any foo' does not contain a comment)
|
||||
- There is no support for multi-line patterns
|
||||
- Shell glob patterns are supported. See Go's "path/filepath".Match
|
||||
- If a pattern begins with a leading !, the match will be negated.
|
||||
- If a pattern begins with a leading /, only paths relatively rooted will match.
|
||||
- If the pattern ends with a trailing /, only directories will match
|
||||
- If a pattern contains no slashes, file basenames are tested (not paths)
|
||||
- The pattern sequence "**", while legal in a glob, will cause an error here
|
||||
(to indicate incompatibility with .gitignore).
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -58,10 +59,10 @@ Example:
|
|||
a[b-d].txt
|
||||
|
||||
Notable differences from .gitignore:
|
||||
- The '**' syntax is not supported.
|
||||
- The globbing library is Go's 'filepath.Match', not fnmatch(3)
|
||||
- Trailing spaces are always ignored (there is no supported escape sequence)
|
||||
- The evaluation of escape sequences has not been tested for compatibility
|
||||
- There is no support for '\!' as a special leading sequence.
|
||||
- The '**' syntax is not supported.
|
||||
- The globbing library is Go's 'filepath.Match', not fnmatch(3)
|
||||
- Trailing spaces are always ignored (there is no supported escape sequence)
|
||||
- The evaluation of escape sequences has not been tested for compatibility
|
||||
- There is no support for '\!' as a special leading sequence.
|
||||
*/
|
||||
package ignore // import "helm.sh/helm/v3/internal/ignore"
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func (c *Client) Search(term string) ([]SearchResult, error) {
|
|||
p.RawQuery = "q=" + url.QueryEscape(term)
|
||||
|
||||
// Create request
|
||||
req, err := http.NewRequest("GET", p.String(), nil)
|
||||
req, err := http.NewRequest(http.MethodGet, p.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "error evaluating symlink %s", path)
|
||||
}
|
||||
log.Printf("found symbolic link in path: %s resolves to %s", path, resolved)
|
||||
log.Printf("found symbolic link in path: %s resolves to %s. Contents of linked file included and used", path, resolved)
|
||||
if info, err = os.Lstat(resolved); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package ensure
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
|
@ -44,7 +43,7 @@ func HelmHome(t *testing.T) func() {
|
|||
// TempDir ensures a scratch test directory for unit testing purposes.
|
||||
func TempDir(t *testing.T) string {
|
||||
t.Helper()
|
||||
d, err := ioutil.TempDir("", "helm")
|
||||
d, err := os.MkdirTemp("", "helm")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -57,13 +56,13 @@ func TempDir(t *testing.T) string {
|
|||
//
|
||||
// You must clean up the directory that is returned.
|
||||
//
|
||||
// tempdir := TempFile(t, "foo", []byte("bar"))
|
||||
// defer os.RemoveAll(tempdir)
|
||||
// filename := filepath.Join(tempdir, "foo")
|
||||
// tempdir := TempFile(t, "foo", []byte("bar"))
|
||||
// defer os.RemoveAll(tempdir)
|
||||
// filename := filepath.Join(tempdir, "foo")
|
||||
func TempFile(t *testing.T, name string, data []byte) string {
|
||||
path := TempDir(t)
|
||||
filename := filepath.Join(path, name)
|
||||
if err := ioutil.WriteFile(filename, data, 0755); err != nil {
|
||||
if err := os.WriteFile(filename, data, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return path
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package test
|
|||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -40,21 +40,12 @@ type HelperT interface {
|
|||
Helper()
|
||||
}
|
||||
|
||||
// AssertGoldenBytes asserts that the give actual content matches the contents of the given filename
|
||||
func AssertGoldenBytes(t TestingT, actual []byte, filename string) {
|
||||
t.Helper()
|
||||
|
||||
if err := compare(actual, path(filename)); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// AssertGoldenString asserts that the given string matches the contents of the given file.
|
||||
func AssertGoldenString(t TestingT, actual, filename string) {
|
||||
t.Helper()
|
||||
|
||||
if err := compare([]byte(actual), path(filename)); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
t.Fatalf("%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,11 +53,11 @@ func AssertGoldenString(t TestingT, actual, filename string) {
|
|||
func AssertGoldenFile(t TestingT, actualFileName string, expectedFilename string) {
|
||||
t.Helper()
|
||||
|
||||
actual, err := ioutil.ReadFile(actualFileName)
|
||||
actual, err := os.ReadFile(actualFileName)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
AssertGoldenBytes(t, actual, expectedFilename)
|
||||
AssertGoldenString(t, string(actual), expectedFilename)
|
||||
}
|
||||
|
||||
func path(filename string) string {
|
||||
|
|
@ -82,13 +73,13 @@ func compare(actual []byte, filename string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile(filename)
|
||||
expected, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read testdata %s", filename)
|
||||
}
|
||||
expected = normalize(expected)
|
||||
if !bytes.Equal(expected, actual) {
|
||||
return errors.Errorf("does not match golden file %s\n\nWANT:\n'%s'\n\nGOT:\n'%s'\n", filename, expected, actual)
|
||||
return errors.Errorf("does not match golden file %s\n\nWANT:\n'%s'\n\nGOT:\n'%s'", filename, expected, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -97,7 +88,7 @@ func update(filename string, in []byte) error {
|
|||
if !*updateGolden {
|
||||
return nil
|
||||
}
|
||||
return ioutil.WriteFile(filename, normalize(in), 0666)
|
||||
return os.WriteFile(filename, normalize(in), 0666)
|
||||
}
|
||||
|
||||
func normalize(in []byte) []byte {
|
||||
|
|
|
|||
9
internal/third_party/dep/fs/fs_test.go
vendored
9
internal/third_party/dep/fs/fs_test.go
vendored
|
|
@ -32,7 +32,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
package fs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -137,7 +136,7 @@ func TestCopyDir(t *testing.T) {
|
|||
t.Fatalf("expected %s to be a directory", dn)
|
||||
}
|
||||
|
||||
got, err := ioutil.ReadFile(fn)
|
||||
got, err := os.ReadFile(fn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -337,7 +336,7 @@ func TestCopyFile(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := ioutil.ReadFile(destf)
|
||||
got, err := os.ReadFile(destf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -396,11 +395,11 @@ func TestCopyFileSymlink(t *testing.T) {
|
|||
// Creating symlinks on Windows require an additional permission
|
||||
// regular users aren't granted usually. So we copy the file
|
||||
// content as a fall back instead of creating a real symlink.
|
||||
srcb, err := ioutil.ReadFile(symlink)
|
||||
srcb, err := os.ReadFile(symlink)
|
||||
if err != nil {
|
||||
t.Fatalf("%+v", err)
|
||||
}
|
||||
dstb, err := ioutil.ReadFile(dst)
|
||||
dstb, err := os.ReadFile(dst)
|
||||
if err != nil {
|
||||
t.Fatalf("%+v", err)
|
||||
}
|
||||
|
|
|
|||
2
internal/third_party/dep/fs/rename.go
vendored
2
internal/third_party/dep/fs/rename.go
vendored
|
|
@ -1,4 +1,4 @@
|
|||
// +build !windows
|
||||
//go:build !windows
|
||||
|
||||
/*
|
||||
Copyright (c) for portions of rename.go are held by The Go Authors, 2016 and are provided under
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// +build windows
|
||||
//go:build windows
|
||||
|
||||
/*
|
||||
Copyright (c) for portions of rename_windows.go are held by The Go Authors, 2016 and are provided under
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ func FindNewReplicaSet(deployment *apps.Deployment, rsList []*apps.ReplicaSet) *
|
|||
|
||||
// EqualIgnoreHash returns true if two given podTemplateSpec are equal, ignoring the diff in value of Labels[pod-template-hash]
|
||||
// We ignore pod-template-hash because:
|
||||
// 1. The hash result would be different upon podTemplateSpec API changes
|
||||
// (e.g. the addition of a new field will cause the hash code to change)
|
||||
// 2. The deployment template won't have hash labels
|
||||
// 1. The hash result would be different upon podTemplateSpec API changes
|
||||
// (e.g. the addition of a new field will cause the hash code to change)
|
||||
// 2. The deployment template won't have hash labels
|
||||
func EqualIgnoreHash(template1, template2 *v1.PodTemplateSpec) bool {
|
||||
t1Copy := template1.DeepCopy()
|
||||
t2Copy := template2.DeepCopy()
|
||||
|
|
|
|||
|
|
@ -19,14 +19,16 @@ package tlsutil
|
|||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// NewClientTLS returns tls.Config appropriate for client auth.
|
||||
func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) {
|
||||
config := tls.Config{}
|
||||
func NewClientTLS(certFile, keyFile, caFile string, insecureSkipTLSverify bool) (*tls.Config, error) {
|
||||
config := tls.Config{
|
||||
InsecureSkipVerify: insecureSkipTLSverify,
|
||||
}
|
||||
|
||||
if certFile != "" && keyFile != "" {
|
||||
cert, err := CertFromFilePair(certFile, keyFile)
|
||||
|
|
@ -52,7 +54,7 @@ func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) {
|
|||
// Returns an error if the file could not be read, a certificate could not
|
||||
// be parsed, or if the file does not contain any certificates
|
||||
func CertPoolFromFile(filename string) (*x509.CertPool, error) {
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("can't read CA file: %v", filename)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,8 +65,9 @@ func TestNewClientTLS(t *testing.T) {
|
|||
certFile := testfile(t, testCertFile)
|
||||
keyFile := testfile(t, testKeyFile)
|
||||
caCertFile := testfile(t, testCaCertFile)
|
||||
insecureSkipTLSverify := false
|
||||
|
||||
cfg, err := NewClientTLS(certFile, keyFile, caCertFile)
|
||||
cfg, err := NewClientTLS(certFile, keyFile, caCertFile, insecureSkipTLSverify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
@ -81,7 +82,7 @@ func TestNewClientTLS(t *testing.T) {
|
|||
t.Fatalf("mismatch tls RootCAs, expecting non-nil")
|
||||
}
|
||||
|
||||
cfg, err = NewClientTLS("", "", caCertFile)
|
||||
cfg, err = NewClientTLS("", "", caCertFile, insecureSkipTLSverify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
@ -96,7 +97,7 @@ func TestNewClientTLS(t *testing.T) {
|
|||
t.Fatalf("mismatch tls RootCAs, expecting non-nil")
|
||||
}
|
||||
|
||||
cfg, err = NewClientTLS(certFile, keyFile, "")
|
||||
cfg, err = NewClientTLS(certFile, keyFile, "", insecureSkipTLSverify)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ var (
|
|||
//
|
||||
// Increment major number for new feature additions and behavioral changes.
|
||||
// Increment minor number for bug fixes and performance enhancements.
|
||||
version = "v3.8"
|
||||
version = "v3.12"
|
||||
|
||||
// metadata is extra build time data
|
||||
metadata = ""
|
||||
|
|
|
|||
|
|
@ -101,8 +101,9 @@ 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 (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) {
|
||||
//
|
||||
// This code has to do with writing files to disk.
|
||||
func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Values, releaseName, outputDir string, subNotes, useReleaseName, includeCrds bool, pr postrender.PostRenderer, interactWithRemote, enableDNS bool) ([]*release.Hook, *bytes.Buffer, string, error) {
|
||||
hs := []*release.Hook{}
|
||||
b := bytes.NewBuffer(nil)
|
||||
|
||||
|
|
@ -120,19 +121,21 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Valu
|
|||
var files map[string]string
|
||||
var err2 error
|
||||
|
||||
// A `helm template` or `helm install --dry-run` should not talk to the remote cluster.
|
||||
// It will break in interesting and exotic ways because other data (e.g. discovery)
|
||||
// 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 && cfg.RESTClientGetter != nil {
|
||||
// A `helm template` should not talk to the remote cluster. However, commands with the flag
|
||||
//`--dry-run` with the value of `false`, `none`, or `server` should try to interact with the cluster.
|
||||
// It may break in interesting and exotic ways because other data (e.g. discovery) is mocked.
|
||||
if interactWithRemote && cfg.RESTClientGetter != nil {
|
||||
restConfig, err := cfg.RESTClientGetter.ToRESTConfig()
|
||||
if err != nil {
|
||||
return hs, b, "", err
|
||||
}
|
||||
files, err2 = engine.RenderWithClient(ch, values, restConfig)
|
||||
e := engine.New(restConfig)
|
||||
e.EnableDNS = enableDNS
|
||||
files, err2 = e.Render(ch, values)
|
||||
} else {
|
||||
files, err2 = engine.Render(ch, values)
|
||||
var e engine.Engine
|
||||
e.EnableDNS = enableDNS
|
||||
files, err2 = e.Render(ch, values)
|
||||
}
|
||||
|
||||
if err2 != nil {
|
||||
|
|
@ -184,13 +187,13 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Valu
|
|||
if includeCrds {
|
||||
for _, crd := range ch.CRDObjects() {
|
||||
if outputDir == "" {
|
||||
fmt.Fprintf(b, "---\n# Source: %s\n%s\n", crd.Name, string(crd.File.Data[:]))
|
||||
fmt.Fprintf(b, "---\n# Source: %s\n%s\n", crd.Filename, string(crd.File.Data[:]))
|
||||
} else {
|
||||
err = writeToFile(outputDir, crd.Filename, string(crd.File.Data[:]), fileWritten[crd.Name])
|
||||
err = writeToFile(outputDir, crd.Filename, string(crd.File.Data[:]), fileWritten[crd.Filename])
|
||||
if err != nil {
|
||||
return hs, b, "", err
|
||||
}
|
||||
fileWritten[crd.Name] = true
|
||||
fileWritten[crd.Filename] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +275,7 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
|
|||
Major: kubeVersion.Major,
|
||||
Minor: kubeVersion.Minor,
|
||||
},
|
||||
HelmVersion: chartutil.DefaultCapabilities.HelmVersion,
|
||||
}
|
||||
return cfg.Capabilities, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
|
@ -17,7 +17,7 @@ package action
|
|||
|
||||
import (
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
fakeclientset "k8s.io/client-go/kubernetes/fake"
|
||||
|
|
@ -44,7 +44,7 @@ func actionConfigFixture(t *testing.T) *Configuration {
|
|||
|
||||
return &Configuration{
|
||||
Releases: storage.Init(driver.NewMemory()),
|
||||
KubeClient: &kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: ioutil.Discard}},
|
||||
KubeClient: &kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: io.Discard}},
|
||||
Capabilities: chartutil.DefaultCapabilities,
|
||||
RegistryClient: registryClient,
|
||||
Log: func(format string, v ...interface{}) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func TestList(t *testing.T) {
|
|||
if err := NewDependency().List(tcase.chart, &buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
test.AssertGoldenBytes(t, buf.Bytes(), tcase.golden)
|
||||
test.AssertGoldenString(t, buf.String(), tcase.golden)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
|
@ -69,8 +70,10 @@ type Install struct {
|
|||
ChartPathOptions
|
||||
|
||||
ClientOnly bool
|
||||
Force bool
|
||||
CreateNamespace bool
|
||||
DryRun bool
|
||||
DryRunOption string
|
||||
DisableHooks bool
|
||||
Replace bool
|
||||
Wait bool
|
||||
|
|
@ -96,6 +99,8 @@ type Install struct {
|
|||
APIVersions chartutil.VersionSet
|
||||
// Used by helm template to render charts with .Release.IsUpgrade. Ignored if Dry-Run is false
|
||||
IsUpgrade bool
|
||||
// Enable DNS lookups when rendering templates
|
||||
EnableDNS bool
|
||||
// Used by helm template to add the release as part of OutputDir path
|
||||
// OutputDir/<ReleaseName>
|
||||
UseReleaseName bool
|
||||
|
|
@ -110,6 +115,7 @@ type ChartPathOptions struct {
|
|||
CertFile string // --cert-file
|
||||
KeyFile string // --key-file
|
||||
InsecureSkipTLSverify bool // --insecure-skip-verify
|
||||
PlainHTTP bool // --plain-http
|
||||
Keyring string // --keyring
|
||||
Password string // --password
|
||||
PassCredentialsAll bool // --pass-credentials
|
||||
|
|
@ -133,6 +139,16 @@ func NewInstall(cfg *Configuration) *Install {
|
|||
return in
|
||||
}
|
||||
|
||||
// SetRegistryClient sets the registry client for the install action
|
||||
func (i *Install) SetRegistryClient(registryClient *registry.Client) {
|
||||
i.ChartPathOptions.registryClient = registryClient
|
||||
}
|
||||
|
||||
// GetRegistryClient get the registry client.
|
||||
func (i *Install) GetRegistryClient() *registry.Client {
|
||||
return i.ChartPathOptions.registryClient
|
||||
}
|
||||
|
||||
func (i *Install) installCRDs(crds []chart.CRD) error {
|
||||
// We do these one file at a time in the order they were read.
|
||||
totalItems := []*resource.Info{}
|
||||
|
|
@ -156,22 +172,38 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
|
|||
totalItems = append(totalItems, res...)
|
||||
}
|
||||
if len(totalItems) > 0 {
|
||||
// Invalidate the local cache, since it will not have the new CRDs
|
||||
// present.
|
||||
discoveryClient, err := i.cfg.RESTClientGetter.ToDiscoveryClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.cfg.Log("Clearing discovery cache")
|
||||
discoveryClient.Invalidate()
|
||||
// Give time for the CRD to be recognized.
|
||||
|
||||
if err := i.cfg.KubeClient.Wait(totalItems, 60*time.Second); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure to force a rebuild of the cache.
|
||||
discoveryClient.ServerGroups()
|
||||
// If we have already gathered the capabilities, we need to invalidate
|
||||
// the cache so that the new CRDs are recognized. This should only be
|
||||
// the case when an action configuration is reused for multiple actions,
|
||||
// as otherwise it is later loaded by ourselves when getCapabilities
|
||||
// is called later on in the installation process.
|
||||
if i.cfg.Capabilities != nil {
|
||||
discoveryClient, err := i.cfg.RESTClientGetter.ToDiscoveryClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.cfg.Log("Clearing discovery cache")
|
||||
discoveryClient.Invalidate()
|
||||
|
||||
_, _ = discoveryClient.ServerGroups()
|
||||
}
|
||||
|
||||
// Invalidate the REST mapper, since it will not have the new CRDs
|
||||
// present.
|
||||
restMapper, err := i.cfg.RESTClientGetter.ToRESTMapper()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resettable, ok := restMapper.(meta.ResettableRESTMapper); ok {
|
||||
i.cfg.Log("Clearing REST mapper cache")
|
||||
resettable.Reset()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -198,15 +230,20 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := chartutil.ProcessDependencies(chrt, vals); err != nil {
|
||||
if err := chartutil.ProcessDependenciesWithMerge(chrt, vals); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var interactWithRemote bool
|
||||
if !i.isDryRun() || i.DryRunOption == "server" || i.DryRunOption == "none" || i.DryRunOption == "false" {
|
||||
interactWithRemote = true
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// On dry run, bail here
|
||||
if i.DryRun {
|
||||
if i.isDryRun() {
|
||||
i.cfg.Log("WARNING: This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.")
|
||||
} else if err := i.installCRDs(crds); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -221,7 +258,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
i.cfg.Capabilities.KubeVersion = *i.KubeVersion
|
||||
}
|
||||
i.cfg.Capabilities.APIVersions = append(i.cfg.Capabilities.APIVersions, i.APIVersions...)
|
||||
i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: ioutil.Discard}
|
||||
i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: io.Discard}
|
||||
|
||||
mem := driver.NewMemory()
|
||||
mem.SetNamespace(i.Namespace)
|
||||
|
|
@ -240,7 +277,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
}
|
||||
|
||||
// special case for helm template --is-upgrade
|
||||
isUpgrade := i.IsUpgrade && i.DryRun
|
||||
isUpgrade := i.IsUpgrade && i.isDryRun()
|
||||
options := chartutil.ReleaseOptions{
|
||||
Name: i.ReleaseName,
|
||||
Namespace: i.Namespace,
|
||||
|
|
@ -256,7 +293,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
rel := i.createRelease(chrt, vals)
|
||||
|
||||
var manifestDoc *bytes.Buffer
|
||||
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.ReleaseName, i.OutputDir, i.SubNotes, i.UseReleaseName, i.IncludeCRDs, i.PostRenderer, i.DryRun)
|
||||
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.ReleaseName, i.OutputDir, i.SubNotes, i.UseReleaseName, i.IncludeCRDs, i.PostRenderer, interactWithRemote, i.EnableDNS)
|
||||
// Even for errors, attach this if available
|
||||
if manifestDoc != nil {
|
||||
rel.Manifest = manifestDoc.String()
|
||||
|
|
@ -292,12 +329,12 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
if !i.ClientOnly && !isUpgrade && len(resources) > 0 {
|
||||
toBeAdopted, err = existingResourceConflict(resources, rel.Name, rel.Namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendered manifests contain a resource that already exists. Unable to continue with install")
|
||||
return nil, errors.Wrap(err, "Unable to continue with install")
|
||||
}
|
||||
}
|
||||
|
||||
// Bail out here if it is a dry run
|
||||
if i.DryRun {
|
||||
if i.isDryRun() {
|
||||
rel.Info.Description = "Dry run complete"
|
||||
return rel, nil
|
||||
}
|
||||
|
|
@ -344,13 +381,25 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
|
|||
return rel, err
|
||||
}
|
||||
rChan := make(chan resultMessage)
|
||||
ctxChan := 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
|
||||
go i.handleContext(ctx, ctxChan, doneChan, rel)
|
||||
select {
|
||||
case result := <-rChan:
|
||||
return result.r, result.e
|
||||
case result := <-ctxChan:
|
||||
return result.r, result.e
|
||||
}
|
||||
}
|
||||
|
||||
// isDryRun returns true if Upgrade is set to run as a DryRun
|
||||
func (i *Install) isDryRun() bool {
|
||||
if i.DryRun || i.DryRunOption == "client" || i.DryRunOption == "server" || i.DryRunOption == "true" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *Install) performInstall(c chan<- resultMessage, rel *release.Release, toBeAdopted kube.ResourceList, resources kube.ResourceList) {
|
||||
|
|
@ -372,7 +421,7 @@ func (i *Install) performInstall(c chan<- resultMessage, rel *release.Release, t
|
|||
return
|
||||
}
|
||||
} else if len(resources) > 0 {
|
||||
if _, err := i.cfg.KubeClient.Update(toBeAdopted, resources, false); err != nil {
|
||||
if _, err := i.cfg.KubeClient.Update(toBeAdopted, resources, i.Force); err != nil {
|
||||
i.reportToRun(c, rel, err)
|
||||
return
|
||||
}
|
||||
|
|
@ -456,17 +505,18 @@ func (i *Install) failRelease(rel *release.Release, err error) (*release.Release
|
|||
//
|
||||
// Roughly, this will return an error if name is
|
||||
//
|
||||
// - empty
|
||||
// - too long
|
||||
// - already in use, and not deleted
|
||||
// - used by a deleted release, and i.Replace is false
|
||||
// - empty
|
||||
// - too long
|
||||
// - already in use, and not deleted
|
||||
// - used by a deleted release, and i.Replace is false
|
||||
func (i *Install) availableName() error {
|
||||
start := i.ReleaseName
|
||||
|
||||
if err := chartutil.ValidateReleaseName(start); err != nil {
|
||||
return errors.Wrapf(err, "release name %q", start)
|
||||
}
|
||||
if i.DryRun {
|
||||
// On dry run, bail here
|
||||
if i.isDryRun() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -673,8 +723,6 @@ 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)
|
||||
}
|
||||
|
|
@ -706,12 +754,17 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
|
|||
getter.WithPassCredentialsAll(c.PassCredentialsAll),
|
||||
getter.WithTLSClientConfig(c.CertFile, c.KeyFile, c.CaFile),
|
||||
getter.WithInsecureSkipVerifyTLS(c.InsecureSkipTLSverify),
|
||||
getter.WithPlainHTTP(c.PlainHTTP),
|
||||
},
|
||||
RepositoryConfig: settings.RepositoryConfig,
|
||||
RepositoryCache: settings.RepositoryCache,
|
||||
RegistryClient: c.registryClient,
|
||||
}
|
||||
|
||||
if registry.IsOCI(name) {
|
||||
dl.Options = append(dl.Options, getter.WithRegistryClient(c.registryClient))
|
||||
}
|
||||
|
||||
if c.Verify {
|
||||
dl.Verify = downloader.VerifyAlways
|
||||
}
|
||||
|
|
@ -751,20 +804,13 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
|
|||
}
|
||||
|
||||
filename, _, err := dl.DownloadTo(name, version, settings.RepositoryCache)
|
||||
if err == nil {
|
||||
lname, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
return lname, nil
|
||||
} else if settings.Debug {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lname, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
|
||||
atVersion := ""
|
||||
if version != "" {
|
||||
atVersion = fmt.Sprintf(" at version %q", version)
|
||||
}
|
||||
|
||||
return filename, errors.Errorf("failed to download %q%s", name, atVersion)
|
||||
return lname, nil
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue