Merge branch 'master' into ilyaz/fix_vm_ctrd_timeout

pull/11632/head
Ilya Zuyev 2021-06-21 14:55:01 -07:00
commit 3ef400ddee
60 changed files with 2730 additions and 424 deletions

18
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: "generate-docs"
on:
push:
branches:
- master
jobs:
generate-docs:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: 1.16.4
stable: true
- name: gendocs
run: |
./hack/generate_docs.sh ${{ secrets.MINIKUBE_BOT_PAT }}

18
.github/workflows/time-to-k8s.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: "time-to-k8s benchmark"
on:
release:
types: [released]
jobs:
benchmark:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init
- uses: actions/setup-go@v2
with:
go-version: 1.16.4
stable: true
- name: Benchmark
run: |
./hack/benchmark/time-to-k8s/time-to-k8s.sh ${{ secrets.MINIKUBE_BOT_PAT }}

4
.gitignore vendored
View File

@ -35,10 +35,6 @@ _testmain.go
#iso version file
deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/etc/VERSION
/pkg/minikube/assets/assets.go-e
/pkg/minikube/assets/assets.go
/pkg/minikube/translate/translations.go
/pkg/minikube/translate/translations.go-e
/minikube
.DS_Store

4
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "site/themes/docsy"]
path = site/themes/docsy
url = https://github.com/google/docsy.git
[submodule "hack/benchmark/time-to-k8s/time-to-k8s"]
path = hack/benchmark/time-to-k8s/time-to-k8s
[submodule "hack/benchmark/time-to-k8s/time-to-k8s-repo"]
path = hack/benchmark/time-to-k8s/time-to-k8s-repo
url = https://github.com/tstromberg/time-to-k8s.git

View File

@ -1,5 +1,37 @@
# Release Notes
## Version 1.21.0 - 2021-06-10
* add more polish translations [#11587](https://github.com/kubernetes/minikube/pull/11587)
* Modify MetricsServer to use v1 api version (instead of v1beta1). [#11584](https://github.com/kubernetes/minikube/pull/11584)
For a more detailed changelog, including changes occuring in pre-release versions, see [CHANGELOG.md](https://github.com/kubernetes/minikube/blob/master/CHANGELOG.md).
Thank you to our contributors for this release!
- Andriy Dzikh
- Ilya Zuyev
- JacekDuszenko
- Medya Ghazizadeh
- Sharif Elgamal
- Steven Powell
Thank you to our PR reviewers for this release!
- spowelljr (11 comments)
- medyagh (2 comments)
- sharifelgamal (2 comments)
- andriyDev (1 comments)
Thank you to our triage members for this release!
- RA489 (12 comments)
- andriyDev (10 comments)
- sharifelgamal (10 comments)
- JacekDuszenko (7 comments)
- spowelljr (5 comments)
Check out our [contributions leaderboard](https://minikube.sigs.k8s.io/docs/contrib/leaderboard/v1.21.0/) for this release!
## Version 1.21.0-beta.0 - 2021-06-02
Features:
* Support setting addons from environmental variables [#11469](https://github.com/kubernetes/minikube/pull/11469)

View File

@ -15,7 +15,7 @@
# Bump these on release - and please check ISO_VERSION for correctness.
VERSION_MAJOR ?= 1
VERSION_MINOR ?= 21
VERSION_BUILD ?= 0-beta.0
VERSION_BUILD ?= 0
RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
VERSION ?= v$(RAW_VERSION)
@ -40,7 +40,7 @@ KVM_GO_VERSION ?= $(GO_VERSION:.0=)
INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1)
BUILDROOT_BRANCH ?= 2020.02.12
REGISTRY?=gcr.io/k8s-minikube
REGISTRY ?= gcr.io/k8s-minikube
# Get git commit id
COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
@ -74,8 +74,7 @@ GOLINT_GOGC ?= 100
GOLINT_OPTIONS = --timeout 7m \
--build-tags "${MINIKUBE_INTEGRATION_BUILD_TAGS}" \
--enable gofmt,goimports,gocritic,golint,gocyclo,misspell,nakedret,stylecheck,unconvert,unparam,dogsled \
--exclude 'variable on range scope.*in function literal|ifElseChain' \
--skip-files "pkg/minikube/translate/translations.go|pkg/minikube/assets/assets.go"
--exclude 'variable on range scope.*in function literal|ifElseChain'
export GO111MODULE := on
@ -130,13 +129,15 @@ MINIKUBE_MARKDOWN_FILES := README.md CONTRIBUTING.md CHANGELOG.md
MINIKUBE_BUILD_TAGS :=
MINIKUBE_INTEGRATION_BUILD_TAGS := integration $(MINIKUBE_BUILD_TAGS)
CMD_SOURCE_DIRS = cmd pkg
CMD_SOURCE_DIRS = cmd pkg deploy/addons translations
SOURCE_DIRS = $(CMD_SOURCE_DIRS) test
SOURCE_PACKAGES = ./cmd/... ./pkg/... ./test/...
SOURCE_PACKAGES = ./cmd/... ./pkg/... ./deploy/addons/... ./translations/... ./test/...
SOURCE_GENERATED = pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go
SOURCE_FILES = $(shell find $(CMD_SOURCE_DIRS) -type f -name "*.go" | grep -v _test.go)
GOTEST_FILES = $(shell find $(CMD_SOURCE_DIRS) -type f -name "*.go" | grep _test.go)
ADDON_FILES = $(shell find "deploy/addons" -type f | grep -v "\.go")
TRANSLATION_FILES = $(shell find "translations" -type f | grep -v "\.go")
ASSET_FILES = $(ADDON_FILES) $(TRANSLATION_FILES)
# kvm2 ldflags
KVM2_LDFLAGS := -X k8s.io/minikube/pkg/drivers/kvm.version=$(VERSION) -X k8s.io/minikube/pkg/drivers/kvm.gitCommitID=$(COMMIT)
@ -195,7 +196,7 @@ ifneq ($(TEST_FILES),)
INTEGRATION_TESTS_TO_RUN := $(addprefix ./test/integration/, $(TEST_HELPERS) $(TEST_FILES))
endif
out/minikube$(IS_EXE): $(SOURCE_GENERATED) $(SOURCE_FILES) go.mod
out/minikube$(IS_EXE): $(SOURCE_FILES) $(ASSET_FILES) go.mod
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) /usr/bin/make $@)
else
@ -244,7 +245,7 @@ minikube-windows-amd64.exe: out/minikube-windows-amd64.exe ## Build Minikube for
eq = $(and $(findstring x$(1),x$(2)),$(findstring x$(2),x$(1)))
out/minikube-%: $(SOURCE_GENERATED) $(SOURCE_FILES)
out/minikube-%: $(SOURCE_FILES) $(ASSET_FILES)
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
else
@ -253,7 +254,7 @@ else
go build -tags "$(MINIKUBE_BUILD_TAGS)" -ldflags="$(MINIKUBE_LDFLAGS)" -a -o $@ k8s.io/minikube/cmd/minikube
endif
out/minikube-linux-armv6: $(SOURCE_GENERATED) $(SOURCE_FILES)
out/minikube-linux-armv6: $(SOURCE_FILES) $(ASSET_FILES)
$(Q)GOOS=linux GOARCH=arm GOARM=6 \
go build -tags "$(MINIKUBE_BUILD_TAGS)" -ldflags="$(MINIKUBE_LDFLAGS)" -a -o $@ k8s.io/minikube/cmd/minikube
@ -310,11 +311,11 @@ iso_in_docker:
--user $(shell id -u):$(shell id -g) --env HOME=/tmp --env IN_DOCKER=1 \
$(ISO_BUILD_IMAGE) /bin/bash
test-iso: $(SOURCE_GENERATED)
test-iso:
go test -v $(INTEGRATION_TESTS_TO_RUN) --tags=iso --minikube-start-args="--iso-url=file://$(shell pwd)/out/buildroot/output/images/rootfs.iso9660"
.PHONY: test-pkg
test-pkg/%: $(SOURCE_GENERATED) ## Trigger packaging test
test-pkg/%: ## Trigger packaging test
go test -v -test.timeout=60m ./$* --tags="$(MINIKUBE_BUILD_TAGS)"
.PHONY: all
@ -364,7 +365,7 @@ else
endif
.PHONY: test
test: $(SOURCE_GENERATED) ## Trigger minikube test
test: ## Trigger minikube test
MINIKUBE_LDFLAGS="${MINIKUBE_LDFLAGS}" ./test.sh
.PHONY: generate-docs
@ -372,7 +373,7 @@ generate-docs: extract out/minikube ## Automatically generate commands documenta
out/minikube generate-docs --path ./site/content/en/docs/commands/ --test-path ./site/content/en/docs/contrib/tests.en.md --code-path ./site/content/en/docs/contrib/errorcodes.en.md
.PHONY: gotest
gotest: $(SOURCE_GENERATED) ## Trigger minikube test
gotest: ## Trigger minikube test
$(if $(quiet),@echo " TEST $@")
$(Q)go test -tags "$(MINIKUBE_BUILD_TAGS)" -ldflags="$(MINIKUBE_LDFLAGS)" $(MINIKUBE_TEST_FILES)
@ -397,33 +398,6 @@ out/coverage.html: out/coverage.out
extract: ## extract internationalization words for translations
go run cmd/extract/extract.go
# Regenerates assets.go when template files have been updated
pkg/minikube/assets/assets.go: $(shell find "deploy/addons" -type f)
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
endif
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/go-bindata/go-bindata/...
$(if $(quiet),@echo " GEN $@")
$(Q)PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
$(Q)-gofmt -s -w $@
@#golint: Dns should be DNS (compat sed)
@sed -i -e 's/Dns/DNS/g' $@ && rm -f ./-e
@#golint: Html should be HTML (compat sed)
@sed -i -e 's/Html/HTML/g' $@ && rm -f ./-e
@#golint: don't use underscores in Go names
@sed -i -e 's/SnapshotStorageK8sIo_volumesnapshot/SnapshotStorageK8sIoVolumesnapshot/g' $@ && rm -f ./-e
pkg/minikube/translate/translations.go: $(shell find "translations/" -type f)
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
endif
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/go-bindata/go-bindata/...
$(if $(quiet),@echo " GEN $@")
$(Q)PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
$(Q)-gofmt -s -w $@
@#golint: Json should be JSON (compat sed)
@sed -i -e 's/Json/JSON/' $@ && rm -f ./-e
.PHONY: cross
cross: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe ## Build minikube for all platform
@ -490,7 +464,7 @@ goimports: ## Run goimports and list the files differs from goimport's
@test -z "`goimports -l $(SOURCE_DIRS)`"
.PHONY: golint
golint: $(SOURCE_GENERATED) ## Run golint
golint: ## Run golint
@golint -set_exit_status $(SOURCE_PACKAGES)
.PHONY: gocyclo
@ -505,17 +479,17 @@ out/linters/golangci-lint-$(GOLINT_VERSION):
# this one is meant for local use
.PHONY: lint
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
lint: $(SOURCE_GENERATED)
lint:
docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:$(GOLINT_VERSION) \
golangci-lint run ${GOLINT_OPTIONS} --skip-dirs "cmd/drivers/kvm|cmd/drivers/hyperkit|pkg/drivers/kvm|pkg/drivers/hyperkit" ./...
else
lint: $(SOURCE_GENERATED) out/linters/golangci-lint-$(GOLINT_VERSION) ## Run lint
lint: out/linters/golangci-lint-$(GOLINT_VERSION) ## Run lint
./out/linters/golangci-lint-$(GOLINT_VERSION) run ${GOLINT_OPTIONS} ./...
endif
# lint-ci is slower version of lint and is meant to be used in ci (travis) to avoid out of memory leaks.
.PHONY: lint-ci
lint-ci: $(SOURCE_GENERATED) out/linters/golangci-lint-$(GOLINT_VERSION) ## Run lint-ci
lint-ci: out/linters/golangci-lint-$(GOLINT_VERSION) ## Run lint-ci
GOGC=${GOLINT_GOGC} ./out/linters/golangci-lint-$(GOLINT_VERSION) run \
--concurrency ${GOLINT_JOBS} ${GOLINT_OPTIONS} ./...
@ -533,7 +507,7 @@ mdlint:
verify-iso: # Make sure the current ISO exists in the expected bucket
gsutil stat gs://$(ISO_BUCKET)/minikube-$(ISO_VERSION).iso
out/docs/minikube.md: $(shell find "cmd") $(shell find "pkg/minikube/constants") $(SOURCE_GENERATED)
out/docs/minikube.md: $(shell find "cmd") $(shell find "pkg/minikube/constants")
go run -ldflags="$(MINIKUBE_LDFLAGS)" -tags gendocs hack/help_text/gen_help_text.go
@ -662,7 +636,7 @@ release-hyperkit-driver: install-hyperkit-driver checksum ## Copy hyperkit using
gsutil cp $(GOBIN)/docker-machine-driver-hyperkit.sha256 gs://minikube/drivers/hyperkit/$(VERSION)/
.PHONY: check-release
check-release: $(SOURCE_GENERATED) ## Execute go test
check-release: ## Execute go test
go test -v ./deploy/minikube/release_sanity_test.go -tags=release
buildroot-image: $(ISO_BUILD_IMAGE) # convenient alias to build the docker container
@ -705,6 +679,21 @@ KICBASE_IMAGE_GCR ?= $(REGISTRY)/kicbase:$(KIC_VERSION)
KICBASE_IMAGE_HUB ?= kicbase/stable:$(KIC_VERSION)
KICBASE_IMAGE_REGISTRIES ?= $(KICBASE_IMAGE_GCR) $(KICBASE_IMAGE_HUB)
.PHONY: local-kicbase
local-kicbase: deploy/kicbase/auto-pause ## Builds the kicbase image and tags it local/kicbase:latest and local/kicbase:$(KIC_VERSION)-$(COMMIT_SHORT)
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION) --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(KICBASE_IMAGE_GCR) ./deploy/kicbase
docker tag local/kicbase:$(KIC_VERSION) local/kicbase:latest
docker tag local/kicbase:$(KIC_VERSION) local/kicbase:$(KIC_VERSION)-$(COMMIT_SHORT)
SED = sed -i
ifeq ($(GOOS),darwin)
SED = sed -i ''
endif
.PHONY: local-kicbase-debug
local-kicbase-debug: local-kicbase ## Builds a local kicbase image and switches source code to point to it
$(SED) 's|Version = .*|Version = \"$(KIC_VERSION)-$(COMMIT_SHORT)\"|;s|baseImageSHA = .*|baseImageSHA = \"\"|;s|gcrRepo = .*|gcrRepo = \"local/kicbase\"|;s|dockerhubRepo = .*|dockerhubRepo = \"local/kicbase\"|' pkg/drivers/kic/types.go
.PHONY: push-kic-base-image
push-kic-base-image: deploy/kicbase/auto-pause docker-multi-arch-builder ## Push multi-arch local/kicbase:latest to all remote registries
ifdef AUTOPUSH
@ -753,7 +742,7 @@ endif
docker push $(IMAGE)
.PHONY: out/gvisor-addon
out/gvisor-addon: $(SOURCE_GENERATED) ## Build gvisor addon
out/gvisor-addon: ## Build gvisor addon
$(if $(quiet),@echo " GO $@")
$(Q)GOOS=linux CGO_ENABLED=0 go build -o $@ cmd/gvisor/gvisor.go
@ -866,8 +855,7 @@ site/themes/docsy/assets/vendor/bootstrap/package.js: ## update the website docs
out/hugo/hugo:
mkdir -p out
test -d out/hugo || git clone https://github.com/gohugoio/hugo.git out/hugo
go get golang.org/dl/go1.16 && go1.16 download
(cd out/hugo && go1.16 build --tags extended)
(cd out/hugo && go build --tags extended)
.PHONY: site
site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo ## Serve the documentation site to localhost
@ -882,16 +870,16 @@ out/mkcmp:
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/mkcmp/main.go
.PHONY: deploy/kicbase/auto-pause # auto pause binary to be used for kic image work around for not passing the whole repo as docker context
deploy/kicbase/auto-pause: $(SOURCE_GENERATED) $(SOURCE_FILES)
deploy/kicbase/auto-pause: $(SOURCE_FILES) $(ASSET_FILES)
GOOS=linux GOARCH=$(GOARCH) go build -o $@ cmd/auto-pause/auto-pause.go
# auto pause binary to be used for ISO
deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/auto-pause: $(SOURCE_GENERATED) $(SOURCE_FILES)
deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/usr/bin/auto-pause: $(SOURCE_FILES) $(ASSET_FILES)
GOOS=linux GOARCH=$(GOARCH) go build -o $@ cmd/auto-pause/auto-pause.go
.PHONY: deploy/addons/auto-pause/auto-pause-hook
deploy/addons/auto-pause/auto-pause-hook: $(SOURCE_GENERATED) ## Build auto-pause hook addon
deploy/addons/auto-pause/auto-pause-hook: ## Build auto-pause hook addon
$(if $(quiet),@echo " GO $@")
$(Q)GOOS=linux CGO_ENABLED=0 go build -a --ldflags '-extldflags "-static"' -tags netgo -installsuffix netgo -o $@ cmd/auto-pause/auto-pause-hook/main.go cmd/auto-pause/auto-pause-hook/config.go cmd/auto-pause/auto-pause-hook/certs.go

View File

@ -122,18 +122,6 @@ var settings = []Setting{
name: config.ReminderWaitPeriodInHours,
set: SetInt,
},
{
name: config.WantReportError,
set: SetBool,
},
{
name: config.WantReportErrorPrompt,
set: SetBool,
},
{
name: config.WantKubectlDownloadMsg,
set: SetBool,
},
{
name: config.WantNoneDriverWarning,
set: SetBool,
@ -146,14 +134,6 @@ var settings = []Setting{
name: Bootstrapper,
set: SetString,
},
{
name: config.ShowDriverDeprecationNotification,
set: SetBool,
},
{
name: config.ShowBootstrapperDeprecationNotification,
set: SetBool,
},
{
name: "insecure-registry",
set: SetString,
@ -172,7 +152,7 @@ var settings = []Setting{
setMap: SetMap,
},
{
name: "embed-certs",
name: config.EmbedCerts,
set: SetBool,
},
{

View File

@ -87,6 +87,24 @@ func (error DeletionError) Error() string {
return error.Err.Error()
}
var hostAndDirsDeleter = func(api libmachine.API, cc *config.ClusterConfig, profileName string) error {
if err := killMountProcess(); err != nil {
out.FailureT("Failed to kill mount process: {{.error}}", out.V{"error": err})
}
deleteHosts(api, cc)
// In case DeleteHost didn't complete the job.
deleteProfileDirectory(profileName)
deleteMachineDirectories(cc)
if err := deleteConfig(profileName); err != nil {
return err
}
return deleteContext(profileName)
}
func init() {
deleteCmd.Flags().BoolVar(&deleteAll, "all", false, "Set flag to delete all profiles")
deleteCmd.Flags().BoolVar(&purge, "purge", false, "Set this flag to delete the '.minikube' folder from your user directory.")
@ -282,23 +300,10 @@ func deleteProfile(ctx context.Context, profile *config.Profile) error {
}
}
if err := killMountProcess(); err != nil {
out.FailureT("Failed to kill mount process: {{.error}}", out.V{"error": err})
}
deleteHosts(api, cc)
// In case DeleteHost didn't complete the job.
deleteProfileDirectory(profile.Name)
deleteMachineDirectories(cc)
if err := deleteConfig(profile.Name); err != nil {
if err := hostAndDirsDeleter(api, cc, profile.Name); err != nil {
return err
}
if err := deleteContext(profile.Name); err != nil {
return err
}
out.Step(style.Deleted, `Removed all traces of the "{{.name}}" cluster.`, out.V{"name": profile.Name})
return nil
}

View File

@ -17,15 +17,18 @@ limitations under the License.
package cmd
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/docker/machine/libmachine"
"github.com/google/go-cmp/cmp"
"github.com/otiai10/copy"
"github.com/spf13/viper"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/localpath"
)
@ -114,6 +117,7 @@ func TestDeleteProfile(t *testing.T) {
t.Logf("load failure: %v", err)
}
hostAndDirsDeleter = hostAndDirsDeleterMock
errs := DeleteProfiles([]*config.Profile{profile})
if len(errs) > 0 {
HandleDeletionErrors(errs)
@ -154,6 +158,17 @@ func TestDeleteProfile(t *testing.T) {
}
}
var hostAndDirsDeleterMock = func(api libmachine.API, cc *config.ClusterConfig, profileName string) error {
return deleteContextTest()
}
func deleteContextTest() error {
if err := cmdcfg.Unset(config.ProfileName); err != nil {
return DeletionError{Err: fmt.Errorf("unset minikube profile: %v", err), Errtype: Fatal}
}
return nil
}
func TestDeleteAllProfiles(t *testing.T) {
td, err := ioutil.TempDir("", "all")
if err != nil {
@ -207,6 +222,7 @@ func TestDeleteAllProfiles(t *testing.T) {
}
profiles := append(validProfiles, inValidProfiles...)
hostAndDirsDeleter = hostAndDirsDeleterMock
errs := DeleteProfiles(profiles)
if errs != nil {

View File

@ -17,43 +17,15 @@ limitations under the License.
package cmd
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/spf13/pflag"
"k8s.io/minikube/pkg/generate"
)
func TestGenerateDocs(t *testing.T) {
pflag.BoolP("help", "h", false, "") // avoid 'Docs are not updated. Please run `make generate-docs` to update commands documentation' error
dir := "../../../site/content/en/docs/commands/"
for _, sc := range RootCmd.Commands() {
t.Run(sc.Name(), func(t *testing.T) {
if sc.Hidden {
t.Skip()
}
fp := filepath.Join(dir, fmt.Sprintf("%s.md", sc.Name()))
expectedContents, err := ioutil.ReadFile(fp)
if err != nil {
t.Fatalf("Docs are not updated. Please run `make generate-docs` to update commands documentation: %v", err)
}
actualContents, err := generate.DocForCommand(sc)
if err != nil {
t.Fatalf("error getting contents: %v", err)
}
if diff := cmp.Diff(actualContents, string(expectedContents)); diff != "" {
t.Fatalf("Docs are not updated. Please run `make generate-docs` to update commands documentation: %s", diff)
}
})
}
}
func TestGenerateTestDocs(t *testing.T) {
tempdir, err := ioutil.TempDir("", "")
if err != nil {
@ -61,12 +33,6 @@ func TestGenerateTestDocs(t *testing.T) {
}
defer os.RemoveAll(tempdir)
docPath := filepath.Join(tempdir, "tests.md")
realPath := "../../../site/content/en/docs/contrib/tests.en.md"
expectedContents, err := ioutil.ReadFile(realPath)
if err != nil {
t.Fatalf("error reading existing file: %v", err)
}
err = generate.TestDocs(docPath, "../../../test/integration")
if err != nil {
@ -77,10 +43,6 @@ func TestGenerateTestDocs(t *testing.T) {
t.Fatalf("error reading generated file: %v", err)
}
if diff := cmp.Diff(string(actualContents), string(expectedContents)); diff != "" {
t.Errorf("Test docs are not updated. Please run `make generate-docs` to update documentation: %s", diff)
}
rest := string(actualContents)
for rest != "" {
rest = checkForNeedsDoc(t, rest)

View File

@ -97,7 +97,7 @@ func Execute() {
if runtime.GOOS == "darwin" && detect.IsAmd64M1Emulation() {
exit.Message(reason.WrongBinaryM1, "You are trying to run amd64 binary on M1 system. Please use darwin/arm64 binary instead (Download at {{.url}}.)",
out.V{"url": notify.DownloadURL(version.GetVersion(), "darwin", "amd64")})
out.V{"url": notify.DownloadURL(version.GetVersion(), "darwin", "arm64")})
}
_, callingCmd := filepath.Split(os.Args[0])
@ -301,14 +301,10 @@ func setupViper() {
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv()
viper.RegisterAlias(config.EmbedCerts, embedCerts)
viper.SetDefault(config.WantUpdateNotification, true)
viper.SetDefault(config.ReminderWaitPeriodInHours, 24)
viper.SetDefault(config.WantReportError, false)
viper.SetDefault(config.WantReportErrorPrompt, true)
viper.SetDefault(config.WantKubectlDownloadMsg, true)
viper.SetDefault(config.WantNoneDriverWarning, true)
viper.SetDefault(config.ShowDriverDeprecationNotification, true)
viper.SetDefault(config.ShowBootstrapperDeprecationNotification, true)
}
func addToPath(dir string) {

View File

@ -162,14 +162,13 @@ func runStart(cmd *cobra.Command, args []string) {
// can be configured as MINIKUBE_IMAGE_REPOSITORY and IMAGE_MIRROR_COUNTRY
// this should be updated to documentation
if len(registryMirror) == 0 {
registryMirror = viper.GetStringSlice("registry_mirror")
registryMirror = viper.GetStringSlice("registry-mirror")
}
if !config.ProfileNameValid(ClusterFlagValue()) {
out.WarningT("Profile name '{{.name}}' is not valid", out.V{"name": ClusterFlagValue()})
exit.Message(reason.Usage, "Only alphanumeric and dashes '-' are permitted. Minimum 2 characters, starting with alphanumeric.")
}
existing, err := config.Load(ClusterFlagValue())
if err != nil && !config.IsNotExist(err) {
kind := reason.HostConfigLoad

135
deploy/addons/assets.go Normal file
View File

@ -0,0 +1,135 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package addons
import "embed"
var (
// AutoPauseAssets assets for auto-pause addon
//go:embed auto-pause/*.tmpl
//go:embed auto-pause/auto-pause.service
//go:embed auto-pause/unpause.lua
AutoPauseAssets embed.FS
// DashboardAssets assets for dashboard addon
//go:embed dashboard/*.yaml dashboard/*.tmpl
DashboardAssets embed.FS
// DefaultStorageClassAssets assets for default-storageclass addon
//go:embed storageclass/storageclass.yaml.tmpl
DefaultStorageClassAssets embed.FS
// PodSecurityPolicyAssets assets for pod-security-policy addon
//go:embed pod-security-policy/pod-security-policy.yaml.tmpl
PodSecurityPolicyAssets embed.FS
// StorageProvisionerAssets assets for storage-provisioner addon
//go:embed storage-provisioner/storage-provisioner.yaml.tmpl
StorageProvisionerAssets embed.FS
// StorageProvisionerGlusterAssets assets for storage-provisioner-gluster addon
//go:embed storage-provisioner-gluster/*.tmpl
StorageProvisionerGlusterAssets embed.FS
// EfkAssets assets for efk addon
//go:embed efk/*.tmpl
EfkAssets embed.FS
// IngressAssets assets for ingress addon
//go:embed ingress/*.tmpl
IngressAssets embed.FS
// IstioProvisionerAssets assets for istio-provisioner addon
//go:embed istio-provisioner/istio-operator.yaml.tmpl
IstioProvisionerAssets embed.FS
// IstioAssets assets for istio addon
//go:embed istio/istio-default-profile.yaml.tmpl
IstioAssets embed.FS
// KubevirtAssets assets for kubevirt addon
//go:embed kubevirt/pod.yaml.tmpl
KubevirtAssets embed.FS
// MetricsServerAssets assets for metrics-server addon
//go:embed metrics-server/*.tmpl
MetricsServerAssets embed.FS
// OlmAssets assets for olm addon
//go:embed olm/*.tmpl
OlmAssets embed.FS
// RegistryAssets assets for registry addon
//go:embed registry/*.tmpl
RegistryAssets embed.FS
// RegistryCredsAssets assets for registry-creds addon
//go:embed registry-creds/registry-creds-rc.yaml.tmpl
RegistryCredsAssets embed.FS
// RegistryAliasesAssets assets for registry-aliases addon
//go:embed registry-aliases/*.tmpl
RegistryAliasesAssets embed.FS
// FreshpodAssets assets for freshpod addon
//go:embed freshpod/freshpod-rc.yaml.tmpl
FreshpodAssets embed.FS
// NvidiaDriverInstallerAssets assets for nvidia-driver-installer addon
//go:embed gpu/nvidia-driver-installer.yaml.tmpl
NvidiaDriverInstallerAssets embed.FS
// NvidiaGpuDevicePluginAssets assets for nvidia-gpu-device-plugin addon
//go:embed gpu/nvidia-gpu-device-plugin.yaml.tmpl
NvidiaGpuDevicePluginAssets embed.FS
// LogviewerAssets assets for logviewer addon
//go:embed logviewer/*.tmpl
LogviewerAssets embed.FS
// GvisorAssets assets for gvisor addon
//go:embed gvisor/*.tmpl gvisor/*.toml
GvisorAssets embed.FS
// HelmTillerAssets assets for helm-tiller addon
//go:embed helm-tiller/*.tmpl
HelmTillerAssets embed.FS
// IngressDNSAssets assets for ingress-dns addon
//go:embed ingress-dns/ingress-dns-pod.yaml.tmpl
IngressDNSAssets embed.FS
// MetallbAssets assets for metallb addon
//go:embed metallb/*.tmpl
MetallbAssets embed.FS
// AmbassadorAssets assets for ambassador addon
//go:embed ambassador/*.tmpl
AmbassadorAssets embed.FS
// GcpAuthAssets assets for gcp-auth addon
//go:embed gcp-auth/*.tmpl
GcpAuthAssets embed.FS
// VolumeSnapshotsAssets assets for volumesnapshots addon
//go:embed volumesnapshots/*.tmpl
VolumeSnapshotsAssets embed.FS
// CsiHostpathDriverAssets assets for csi-hostpath-driver addon
//go:embed csi-hostpath-driver/deploy/*.tmpl csi-hostpath-driver/rbac/*.tmpl
CsiHostpathDriverAssets embed.FS
)

View File

@ -1,4 +1,12 @@
[
{
"name": "v1.21.0",
"checksums": {
"darwin": "e2043883ca993b2a65396d379823dab6404dd842d0cc2a81348d247b01785070",
"linux": "5d423a00a24fdfbb95627a3fadbf58540fc4463be2338619257c529f93cf061b",
"windows": "74c961877798531ab8e53e2590bfae3cee7690d0c2e0614fdb44339e065124b5"
}
},
{
"name": "v1.20.0",
"checksums": {

View File

@ -0,0 +1,205 @@
# Periodically tell user about minikube features/tips and tricks
* First proposed: 2021-06-18
* Authors: Peixuan Ding (@dinever)
## Reviewer Priorities
Please review this proposal with the following priorities:
* Does this fit with minikube's [principles](https://minikube.sigs.k8s.io/docs/concepts/principles/)?
* Are there other approaches to consider?
* Could the implementation be made simpler?
* Are there usability, reliability, or technical debt concerns?
Please leave the above text in your proposal as instructions to the reader.
## Summary
minikube has lots of great features. We want to proactively remind users that
those features are available.
To achieve this, we can have a tips feature that randomly shows a tip
from a curated list whenever the user starts a new minikube profile.
For example:
![Screenshot from 2021-06-18 00-58-02](https://user-images.githubusercontent.com/1311594/122508665-53bd6380-cfd0-11eb-9e99-a6c5935514d5.png)
## Goals
* Store a list of tips in a static file
* Show a random minikube usage tip each time a user starts a minikube profile
* Have the tips synced to the Hugo docs website to make those available through docs
* Allow user to disable the Tips feature with minikube config
## Non-Goals
* Modify any existing functionalities or docs
## Design Details
First, we need a static file to store all the tips, we can have a YAML file at [pkg/generate/tips/tips.yaml](https://github.com/kubernetes/minikube/tree/master/pkg/generate):
```YAML
tips:
- |
You can specify any Kubernetes version you want. For example:
```
minikube start --kubernetes-version=v1.19.0
```
- |
You can use minikube's built-in kubectl. For example:
```
minikube kubectl -- get pods
```
- |
minikube has the built-in Kubernetes Dashboard UI. To access it:
```
minikube dashboard
```
```
Use `goembed` to embed this file into the minikube binary.
The current `out.Boxed` has a hard-coded style (red). I propose to add another `out.BoxedWithConfig` method to allow
output with customized style:
```go
// BoxedWithConfig writes a templated message in a box with customized style config to stdout
func BoxedWithConfig(cfg box.Config, st style.Enum, title string, format string, a ...V) {
}
```
Whenever minikube successfully starts, we randomly choose a tip.
Before printing it out, we need to do some regex replacement to strip the markdown syntax
for better view experience in Terminal:
From this:
``````markdown
You can specify any Kubernetes version you want. For example:
```
minikube start --kubernetes-version=v1.19.0
```
``````
To this:
```markdown
You can specify any Kubernetes version you want. For example:
minikube start --kubernetes-version=v1.19.0
```
Then we can print out the tip:
```go
boxCfg := out.BoxConfig{
Config: box.Config{
Py: 1,
Px: 5,
TitlePos: "Top",
Type: "Round",
Color: tipBoxColor,
},
Title: tipTitle,
Icon: style.Tip,
}
out.BoxedWithConfig(boxCfg, tips.Tips[chosen] + "\n\n" + tipSuffix)
```
![Screenshot from 2021-06-18 00-58-02](https://user-images.githubusercontent.com/1311594/122508665-53bd6380-cfd0-11eb-9e99-a6c5935514d5.png)
User can choose to disable this through `minikube config set disable-tips true`
We will have `make generate-docs` generating the docs site based on this YAML file as well.
We can have a `Nice to know` sub-page under `FAQ`?
![Screenshot from 2021-06-18 01-00-30](https://user-images.githubusercontent.com/1311594/122508827-a139d080-cfd0-11eb-98bb-f7c3c1c604c2.png)
### About the tip collection
I plan to start with the command lines and cover almost all CLI usages of minikube.
That includes but not limited to:
- addons
- cached images
- command line completion
- config
- file copy
- dashboard
- delete minikube cluster
- configure minikube's docker/podman env
- image build / load / ls / rm
- ip
- logging
- kubectl
- mount file directory
- multi-node
- pause/unpause to save resource
- multi-profile
- surface URL to a k8s service
- ssh into minikube
- status
- tunnel to connect to LB
- update-check to check versions
- update-context
### Implementation
I plan to open at least 4 PRs:
1. `out.Boxed` with custom style
2. random `tips` display with ability to disable through config, with an initial set of about 10 tips
3. `make generate-docs` to sync tips to docs
4. Add more tips
## Alternatives Considered
1. Is there a more preferred file format to YAML?
2. Maybe we just want to sync the tips to the `FAQ` page list instead of creating a new page?
3. Instead of the file format I proposed, maybe add a `question` field?
```yaml
tips:
- question: How to specify a different Kubernetes version?
answer: |
You can specify any Kubernetes version you want. For example:
```
minikube start --kubernetes-version=v1.19.0
```
- question: Do I have to install `kubectl` myself?
answer: |
You can use minikube's built-in kubectl. For example:
```
minikube kubectl -- get pods
```
- question: How do I access the Kubernetes Dashboard UI?
answer: |
minikube has the built-in Kubernetes Dashboard UI. To access it:
```
minikube dashboard
```
```
On the docs side we can show both questions and answers. On the CLI side
we can either show both questions and answers, or just show the answers
to make it more compact.
![Screenshot from 2021-06-18 01-25-54](https://user-images.githubusercontent.com/1311594/122510785-2c689580-cfd4-11eb-9fd0-0a0ff344e3cc.png)

8
go.mod
View File

@ -33,7 +33,7 @@ require (
github.com/google/go-github/v32 v32.1.0
github.com/google/slowjam v0.0.0-20200530021616-df27e642fe7b
github.com/google/uuid v1.2.0
github.com/hashicorp/go-getter v1.5.2
github.com/hashicorp/go-getter v1.5.4
github.com/hashicorp/go-retryablehttp v0.7.0
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 // indirect
github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect
@ -71,7 +71,7 @@ require (
github.com/shirou/gopsutil/v3 v3.21.5
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/spf13/viper v1.8.0
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
go.opencensus.io v0.23.0
@ -84,11 +84,11 @@ require (
golang.org/x/mod v0.4.2
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72
golang.org/x/text v0.3.6
gonum.org/v1/plot v0.9.0
google.golang.org/api v0.47.0
google.golang.org/api v0.48.0
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
gopkg.in/yaml.v2 v2.4.0
gotest.tools/v3 v3.0.3 // indirect

88
go.sum
View File

@ -21,8 +21,9 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0 h1:bAMqZidYkmIsUqe6PtkEPT7Q+vfizScn+jfNA6jwK9c=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -66,7 +67,6 @@ github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocm
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Delta456/box-cli-maker/v2 v2.2.1 h1:uTcuvT6Ty+LBHuRUdFrJBpqP9RhtLxI5+5ZpKYAUuVw=
@ -124,6 +124,7 @@ github.com/alonyb/spinner v1.12.7 h1:FflTMA9I2xRd8OQ5swyZY6Q1DFeaicA/bWo6/oM82a8
github.com/alonyb/spinner v1.12.7/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@ -148,6 +149,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
@ -269,6 +271,7 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -421,6 +424,7 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -467,6 +471,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
@ -498,8 +503,9 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -511,6 +517,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/slowjam v0.0.0-20200530021616-df27e642fe7b h1:x3aElhKtGmXLo6RI2FJSBaPBT0acmn2LFfKVP1CqH8o=
github.com/google/slowjam v0.0.0-20200530021616-df27e642fe7b/go.mod h1:i4b4iDjZbKPkbD7z9Ycy4gtcALPoh8E9O3+wvtw7IB0=
@ -546,15 +553,16 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-getter v1.5.2 h1:XDo8LiAcDisiqZdv0TKgz+HtX3WN7zA2JD1R1tjsabE=
github.com/hashicorp/go-getter v1.5.2/go.mod h1:orNH3BTYLu/fIxGIdLjLoAJHWMDQ/UKQr5O4m3iBuoo=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.5.4 h1:/A0xlardcuhx8SEe1rh1371xV7Yi4j3xeluu53VXeyg=
github.com/hashicorp/go-getter v1.5.4/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@ -623,8 +631,9 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@ -666,6 +675,7 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -695,8 +705,9 @@ github.com/machine-drivers/docker-machine-driver-vmware v0.1.3/go.mod h1:p2hY99U
github.com/machine-drivers/machine v0.7.1-0.20210306082426-fcb2ad5bcb17 h1:fQoDTuCuJ30R+D6TSB9SALB+J3jUMa8ID8YPfmSDA20=
github.com/machine-drivers/machine v0.7.1-0.20210306082426-fcb2ad5bcb17/go.mod h1:79Uwa2hGd5S39LDJt58s8JZcIhGEK6pkq9bsuTbFWbk=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -750,8 +761,9 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/hyperkit v0.0.0-20210108224842-2f061e447e14 h1:XGy4iMfaG4r1uZKZQmEPSYSH0Nj5JJuKgPNUhWGQ08E=
github.com/moby/hyperkit v0.0.0-20210108224842-2f061e447e14/go.mod h1:aBcAEoy5u01cPAYvosR85gzSrMZ0TVVnkPytOQN+9z8=
@ -838,8 +850,9 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
@ -855,6 +868,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v0.0.0-20161223203901-3a8809bd8a80 h1:DQFOykp5w+HOykOMzd2yOX5P6ty58Ggiu2rthHgcNQg=
github.com/pkg/profile v0.0.0-20161223203901-3a8809bd8a80/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@ -900,6 +914,7 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
@ -940,10 +955,12 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
@ -961,8 +978,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.0 h1:QRwDgoG8xX+kp69di68D+YYTCWfYEckbZRfUlEIAal0=
github.com/spf13/viper v1.8.0/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -1035,6 +1052,9 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@ -1058,12 +1078,15 @@ go.opentelemetry.io/otel/sdk v0.16.0/go.mod h1:Jb0B4wrxerxtBeapvstmAZvJGQmvah4dH
go.opentelemetry.io/otel/trace v0.17.0 h1:SBOj64/GAOyWzs5F680yW1ITIfJkm6cJWL2YAvuL9xY=
go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f h1:hXVePvSFG7tPGX4Pwk1d10ePFfoTCc0QmISfpKOHsS8=
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f/go.mod h1:fYw7AShPAhGMdXqA9gRadk/CcMsvLlClpE5oBwnS3dM=
@ -1083,6 +1106,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -1207,6 +1231,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@ -1313,8 +1338,9 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72 h1:VqE9gduFZ4dbR7XoL77lHFp0/DyDUBKSXK7CMFkVcV0=
golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -1400,8 +1426,9 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1441,9 +1468,11 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA=
google.golang.org/api v0.47.0 h1:sQLWZQvP6jPGIP4JGPkJu4zHswrv81iobiyszr3b/0I=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0 h1:RDAPWfNFY06dffEXfn7hZF5Fr1ZbnChzfQZAPyBd1+I=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1478,6 +1507,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
@ -1501,8 +1531,10 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210420162539-3c870d7478d2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 h1:z+j74wi4yV+P7EtK9gPLGukOk7mFOy9wMQaC0wNb7eY=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08 h1:pc16UedxnxXXtGxHCSUhafAoVHQZ0yXl8ZelMH4EETc=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@ -1521,14 +1553,17 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -1560,8 +1595,9 @@ gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
@ -1575,6 +1611,7 @@ gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -1582,8 +1619,9 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

View File

@ -17,7 +17,7 @@
set -e
install_kind() {
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.0/kind-linux-amd64
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local
}
@ -31,31 +31,58 @@ install_minikube() {
sudo install ./out/minikube /usr/local/bin/minikube
}
install_gh() {
export access_token="$1"
# Make sure gh is installed and configured
./hack/jenkins/installers/check_install_gh.sh
}
config_git() {
git config user.name "minikube-bot"
git config user.email "minikube-bot@google.com"
}
create_branch() {
git checkout -b addTimeToK8s"$1"
}
run_benchmark() {
( cd ./hack/benchmark/time-to-k8s/time-to-k8s/ &&
pwd
( cd ./hack/benchmark/time-to-k8s/time-to-k8s-repo/ &&
git submodule update --init &&
go run . --config local-kubernetes.yaml --iterations 5 --output output.csv )
}
generate_chart() {
go run ./hack/benchmark/time-to-k8s/chart.go --csv ./hack/benchmark/time-to-k8s/time-to-k8s/output.csv --output ./site/static/images/benchmarks/timeToK8s/"$1".png
go run ./hack/benchmark/time-to-k8s/chart.go --csv ./hack/benchmark/time-to-k8s/time-to-k8s-repo/output.csv --output ./site/static/images/benchmarks/timeToK8s/"$1".png
}
create_page() {
printf -- "---\ntitle: \"%s Benchmark\"\nlinkTitle: \"%s Benchmark\"\nweight: 1\n---\n\n![time-to-k8s](/images/benchmarks/timeToK8s/%s.png)\n" "$1" "$1" "$1" > ./site/content/en/docs/benchmarks/timeToK8s/"$1".md
}
commit_chart() {
commit_changes() {
git add ./site/static/images/benchmarks/timeToK8s/"$1".png ./site/content/en/docs/benchmarks/timeToK8s/"$1".md
git commit -m 'update time-to-k8s chart'
git commit -m "add time-to-k8s benchmark for $1"
}
create_pr() {
git remote add minikube-bot https://minikube-bot:"$2"@github.com/minikube-bot/minikube.git
git push -u minikube-bot addTimeToK8s"$1"
gh pr create --repo kubernetes/minikube --base master --title "Add time-to-k8s benchmark for $1" --body "Updating time-to-k8s benchmark as part of the release process"
}
install_kind
install_k3d
install_minikube
VERSION=$(minikube version --short)
install_gh "$1"
config_git
VERSION=$(minikube version --short)
create_branch "$VERSION"
run_benchmark
generate_chart "$VERSION"
create_page "$VERSION"
commit_chart "$VERSION"
commit_changes "$VERSION"
create_pr "$VERSION" "$1"

53
hack/generate_docs.sh Executable file
View File

@ -0,0 +1,53 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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 -x
if [ "$#" -ne 1 ]; then
# there's no secret and therefore no reason to run this script
exit 0
fi
install_gh() {
export access_token="$1"
# Make sure gh is installed and configured
./hack/jenkins/installers/check_install_gh.sh
}
config_git() {
git config user.name "minikube-bot"
git config user.email "minikube-bot@google.com"
}
make generate-docs
# If there are changes, open a PR
git diff-index --quiet HEAD --
if [ $? -gt 0 ]; then
install_gh $1
config_git
branch=gendocs$(date +%s%N)
git checkout -b $branch
git add .
git commit -m "Update generate-docs"
git remote add minikube-bot https://minikube-bot:$1@github.com/minikube-bot/minikube.git
git push -u minikube-bot $branch
gh pr create --repo kubernetes/minukube --base master --title "Update generate-docs" --body "Committing changes resulting from \`make generate-docs\`"
fi

View File

@ -419,7 +419,7 @@ fi
touch "${HTML_OUT}"
touch "${SUMMARY_OUT}"
gopogh_status=$(gopogh -in "${JSON_OUT}" -out_html "${HTML_OUT}" -out_summary "${SUMMARY_OUT}" -name "${JOB_NAME}" -pr "${MINIKUBE_LOCATION}" -repo github.com/kubernetes/minikube/ -details "${COMMIT}") || true
gopogh_status=$(gopogh -in "${JSON_OUT}" -out_html "${HTML_OUT}" -out_summary "${SUMMARY_OUT}" -name "${JOB_NAME}" -pr "${MINIKUBE_LOCATION}" -repo github.com/kubernetes/minikube/ -details "${COMMIT}:$(date +%Y-%m-%d)") || true
fail_num=$(echo $gopogh_status | jq '.NumberOfFail')
test_num=$(echo $gopogh_status | jq '.NumberOfTests')
pessimistic_status="${fail_num} / ${test_num} failures"
@ -441,6 +441,11 @@ if [ -z "${EXTERNAL}" ]; then
gsutil -qm cp "${HTML_OUT}" "gs://${JOB_GCS_BUCKET}.html" || true
echo ">> uploading ${SUMMARY_OUT}"
gsutil -qm cp "${SUMMARY_OUT}" "gs://${JOB_GCS_BUCKET}_summary.json" || true
if [[ "${MINIKUBE_LOCATION}" == "master" ]]; then
./test-flake-chart/upload_tests.sh "${SUMMARY_OUT}"
elif [[ "${JOB_NAME}" == "Docker_Linux" || "${JOB_NAME}" == "Docker_Linux_containerd" || "${JOB_NAME}" == "KVM_Linux" || "${JOB_NAME}" == "KVM_Linux_containerd" ]]; then
./test-flake-chart/report_flakes.sh "${MINIKUBE_LOCATION}" "${SUMMARY_OUT}" "${JOB_NAME}"
fi
else
# Otherwise, put the results in a predictable spot so the upload job can find them
REPORTS_PATH=test_reports

View File

@ -0,0 +1,31 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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.
# Collects all test data manually, processes it, and uploads to GCS. This will
# overwrite any existing data. This should only be done for a dryrun, new data
# should be handled exclusively through upload_tests.sh.
# Example usage: ./collect_data_manual.sh
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# 1) "cat" together all summary files.
# 2) Process all summary files.
# 3) Optimize the resulting data.
# 4) Store in GCS bucket.
gsutil cat gs://minikube-builds/logs/master/*/*_summary.json \
| $DIR/process_data.sh \
| $DIR/optimize_data.sh \
| gsutil cp - gs://minikube-flake-rate/data.csv

View File

@ -0,0 +1,264 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"runtime/debug"
"sort"
"strconv"
"strings"
"time"
)
var (
dataCsv = flag.String("data-csv", "", "Source data to compute flake rates on")
dateRange = flag.Uint("date-range", 5, "Number of test dates to consider when computing flake rate")
)
func main() {
flag.Parse()
file, err := os.Open(*dataCsv)
if err != nil {
exit("Unable to read data CSV", err)
}
testEntries := readData(file)
splitEntries := splitData(testEntries)
filteredEntries := filterRecentEntries(splitEntries, *dateRange)
flakeRates := computeFlakeRates(filteredEntries)
averageDurations := computeAverageDurations(filteredEntries)
fmt.Println("Environment,Test,Flake Rate,Duration")
for environment, environmentSplit := range flakeRates {
for test, flakeRate := range environmentSplit {
duration := averageDurations[environment][test]
fmt.Printf("%s,%s,%.2f,%.3f\n", environment, test, flakeRate*100, duration)
}
}
}
// One entry of a test run.
// Example: TestEntry {
// name: "TestFunctional/parallel/LogsCmd",
// environment: "Docker_Linux",
// date: time.Now,
// status: "Passed",
// duration: 0.1,
// }
type testEntry struct {
name string
environment string
date time.Time
status string
duration float32
}
// A map with keys of (environment, test_name) to values of slcies of TestEntry.
type splitEntryMap map[string]map[string][]testEntry
// Reads CSV `file` and consumes each line to be a single TestEntry.
func readData(file io.Reader) []testEntry {
testEntries := []testEntry{}
fileReader := bufio.NewReaderSize(file, 256)
previousLine := []string{"", "", "", "", "", ""}
firstLine := true
for {
lineBytes, _, err := fileReader.ReadLine()
if err != nil {
if err == io.EOF {
break
}
exit("Error reading data CSV", err)
}
line := string(lineBytes)
fields := strings.Split(line, ",")
if firstLine {
if len(fields) != 6 {
exit(fmt.Sprintf("Data CSV in incorrect format. Expected 6 columns, but got %d", len(fields)), fmt.Errorf("bad CSV format"))
}
firstLine = false
}
for i, field := range fields {
if field == "" {
fields[i] = previousLine[i]
}
}
if len(fields) != 6 {
fmt.Printf("Found line with wrong number of columns. Expectd 6, but got %d - skipping\n", len(fields))
continue
}
previousLine = fields
if fields[4] == "Passed" || fields[4] == "Failed" {
date, err := time.Parse("2006-01-02", fields[1])
if err != nil {
fmt.Printf("Failed to parse date: %v\n", err)
continue
}
duration, err := strconv.ParseFloat(fields[5], 32)
if err != nil {
fmt.Printf("Failed to parse duration: %v\n", err)
continue
}
testEntries = append(testEntries, testEntry{
name: fields[3],
environment: fields[2],
date: date,
status: fields[4],
duration: float32(duration),
})
}
}
return testEntries
}
// Splits `testEntries` up into maps indexed first by environment and then by test.
func splitData(testEntries []testEntry) splitEntryMap {
splitEntries := make(splitEntryMap)
for _, entry := range testEntries {
appendEntry(splitEntries, entry.environment, entry.name, entry)
}
return splitEntries
}
// Appends `entry` to `splitEntries` at the `environment` and `test`.
func appendEntry(splitEntries splitEntryMap, environment, test string, entry testEntry) {
// Lookup the environment.
environmentSplit, ok := splitEntries[environment]
if !ok {
// If the environment map is missing, make a map for this environment and store it.
environmentSplit = make(map[string][]testEntry)
splitEntries[environment] = environmentSplit
}
// Lookup the test.
testSplit, ok := environmentSplit[test]
if !ok {
// If the test is missing, make a slice for this test.
testSplit = make([]testEntry, 0)
// The slice is not inserted, since it will be replaced anyway.
}
environmentSplit[test] = append(testSplit, entry)
}
// Filters `splitEntries` to include only the most recent `date_range` dates.
func filterRecentEntries(splitEntries splitEntryMap, dateRange uint) splitEntryMap {
filteredEntries := make(splitEntryMap)
for environment, environmentSplit := range splitEntries {
for test, testSplit := range environmentSplit {
dates := make([]time.Time, len(testSplit))
for _, entry := range testSplit {
dates = append(dates, entry.date)
}
// Sort dates from future to past.
sort.Slice(dates, func(i, j int) bool {
return dates[j].Before(dates[i])
})
datesInRange := make([]time.Time, 0, dateRange)
var lastDate time.Time
// Go through each date.
for _, date := range dates {
// If date is the same as last date, ignore it.
if date.Equal(lastDate) {
continue
}
// Add the date.
datesInRange = append(datesInRange, date)
lastDate = date
// If the date_range has been hit, break out.
if uint(len(datesInRange)) == dateRange {
break
}
}
for _, entry := range testSplit {
// Look for the first element <= entry.date
index := sort.Search(len(datesInRange), func(i int) bool {
return !datesInRange[i].After(entry.date)
})
// If no date is <= entry.date, or the found date does not equal entry.date.
if index == len(datesInRange) || !datesInRange[index].Equal(entry.date) {
continue
}
appendEntry(filteredEntries, environment, test, entry)
}
}
}
return filteredEntries
}
// Computes the flake rates over each entry in `splitEntries`.
func computeFlakeRates(splitEntries splitEntryMap) map[string]map[string]float32 {
flakeRates := make(map[string]map[string]float32)
for environment, environmentSplit := range splitEntries {
for test, testSplit := range environmentSplit {
failures := 0
for _, entry := range testSplit {
if entry.status == "Failed" {
failures++
}
}
setValue(flakeRates, environment, test, float32(failures)/float32(len(testSplit)))
}
}
return flakeRates
}
// Computes the average durations over each entry in `splitEntries`.
func computeAverageDurations(splitEntries splitEntryMap) map[string]map[string]float32 {
averageDurations := make(map[string]map[string]float32)
for environment, environmentSplit := range splitEntries {
for test, testSplit := range environmentSplit {
durationSum := float32(0)
for _, entry := range testSplit {
durationSum += entry.duration
}
if len(testSplit) != 0 {
durationSum /= float32(len(testSplit))
}
setValue(averageDurations, environment, test, durationSum)
}
}
return averageDurations
}
// Sets the `value` of keys `environment` and `test` in `mapEntries`.
func setValue(mapEntries map[string]map[string]float32, environment, test string, value float32) {
// Lookup the environment.
environmentRates, ok := mapEntries[environment]
if !ok {
// If the environment map is missing, make a map for this environment and store it.
environmentRates = make(map[string]float32)
mapEntries[environment] = environmentRates
}
environmentRates[test] = value
}
// exit will exit and clean up minikube
func exit(msg string, err error) {
fmt.Printf("WithError(%s)=%v called from:\n%s", msg, err, debug.Stack())
os.Exit(60)
}

View File

@ -0,0 +1,492 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strings"
"testing"
"time"
)
func simpleDate(year int, day int) time.Time {
return time.Date(year, time.January, day, 0, 0, 0, 0, time.UTC)
}
func compareEntrySlices(t *testing.T, actualData, expectedData []testEntry, extra string) {
if extra != "" {
extra = fmt.Sprintf(" (%s)", extra)
}
for i, actual := range actualData {
if len(expectedData) <= i {
t.Errorf("Received unmatched actual element at index %d%s. Actual: %v", i, extra, actual)
continue
}
expected := expectedData[i]
if actual != expected {
t.Errorf("Elements differ at index %d%s. Expected: %v, Actual: %v", i, extra, expected, actual)
}
}
if len(actualData) < len(expectedData) {
for i := len(actualData); i < len(expectedData); i++ {
t.Errorf("Missing unmatched expected element at index %d%s. Expected: %v", i, extra, expectedData[i])
}
}
}
func TestReadData(t *testing.T) {
actualData := readData(strings.NewReader(
`A,B,C,D,E,F
hash,2000-01-01,env1,test1,Passed,1
hash,2001-01-01,env2,test2,Failed,0.5
hash,,,test1,,0.6
hash,2002-01-01,,,Passed,0.9
hash,2003-01-01,env3,test3,Passed,2`,
))
expectedData := []testEntry{
{
name: "test1",
environment: "env1",
date: simpleDate(2000, 1),
status: "Passed",
duration: 1,
},
{
name: "test2",
environment: "env2",
date: simpleDate(2001, 1),
status: "Failed",
duration: 0.5,
},
{
name: "test1",
environment: "env2",
date: simpleDate(2001, 1),
status: "Failed",
duration: 0.6,
},
{
name: "test1",
environment: "env2",
date: simpleDate(2002, 1),
status: "Passed",
duration: 0.9,
},
{
name: "test3",
environment: "env3",
date: simpleDate(2003, 1),
status: "Passed",
duration: 2,
},
}
compareEntrySlices(t, actualData, expectedData, "")
}
func compareSplitData(t *testing.T, actual, expected splitEntryMap) {
for environment, actualTests := range actual {
expectedTests, environmentOk := expected[environment]
if !environmentOk {
t.Errorf("Unexpected environment %s in actual", environment)
continue
}
for test, actualEntries := range actualTests {
expectedEntries, testOk := expectedTests[test]
if !testOk {
t.Errorf("Unexpected test %s (in environment %s) in actual", test, environment)
continue
}
compareEntrySlices(t, actualEntries, expectedEntries, fmt.Sprintf("environment %s, test %s", environment, test))
}
for test := range expectedTests {
_, testOk := actualTests[test]
if !testOk {
t.Errorf("Missing expected test %s (in environment %s) in actual", test, environment)
}
}
}
for environment := range expected {
_, environmentOk := actual[environment]
if !environmentOk {
t.Errorf("Missing expected environment %s in actual", environment)
}
}
}
func TestSplitData(t *testing.T) {
entryE1T1_1, entryE1T1_2 := testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 1),
status: "Passed",
}, testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 2),
status: "Passed",
}
entryE1T2 := testEntry{
name: "test2",
environment: "env1",
date: simpleDate(2000, 1),
status: "Passed",
}
entryE2T1 := testEntry{
name: "test1",
environment: "env2",
date: simpleDate(2000, 1),
status: "Passed",
}
entryE2T2 := testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2000, 1),
status: "Passed",
}
actual := splitData([]testEntry{entryE1T1_1, entryE1T1_2, entryE1T2, entryE2T1, entryE2T2})
expected := splitEntryMap{
"env1": {
"test1": {entryE1T1_1, entryE1T1_2},
"test2": {entryE1T2},
},
"env2": {
"test1": {entryE2T1},
"test2": {entryE2T2},
},
}
compareSplitData(t, actual, expected)
}
func TestFilterRecentEntries(t *testing.T) {
entryE1T1R1, entryE1T1R2, entryE1T1R3, entryE1T1O1, entryE1T1O2 := testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 4),
status: "Passed",
}, testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
}, testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
}, testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 2),
status: "Passed",
}, testEntry{
name: "test1",
environment: "env1",
date: simpleDate(2000, 1),
status: "Passed",
}
entryE1T2R1, entryE1T2R2, entryE1T2O1 := testEntry{
name: "test2",
environment: "env1",
date: simpleDate(2001, 3),
status: "Passed",
}, testEntry{
name: "test2",
environment: "env1",
date: simpleDate(2001, 2),
status: "Passed",
}, testEntry{
name: "test2",
environment: "env1",
date: simpleDate(2001, 1),
status: "Passed",
}
entryE2T2R1, entryE2T2R2, entryE2T2O1 := testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2003, 3),
status: "Passed",
}, testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2003, 2),
status: "Passed",
}, testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2003, 1),
status: "Passed",
}
actualData := filterRecentEntries(splitEntryMap{
"env1": {
"test1": {
entryE1T1R1,
entryE1T1R2,
entryE1T1R3,
entryE1T1O1,
entryE1T1O2,
},
"test2": {
entryE1T2R1,
entryE1T2R2,
entryE1T2O1,
},
},
"env2": {
"test2": {
entryE2T2R1,
entryE2T2R2,
entryE2T2O1,
},
},
}, 2)
expectedData := splitEntryMap{
"env1": {
"test1": {
entryE1T1R1,
entryE1T1R2,
entryE1T1R3,
},
"test2": {
entryE1T2R1,
entryE1T2R2,
},
},
"env2": {
"test2": {
entryE2T2R1,
entryE2T2R2,
},
},
}
compareSplitData(t, actualData, expectedData)
}
func compareValues(t *testing.T, actualValues, expectedValues map[string]map[string]float32) {
for environment, actualTests := range actualValues {
expectedTests, environmentOk := expectedValues[environment]
if !environmentOk {
t.Errorf("Unexpected environment %s in actual", environment)
continue
}
for test, actualValue := range actualTests {
expectedValue, testOk := expectedTests[test]
if !testOk {
t.Errorf("Unexpected test %s (in environment %s) in actual", test, environment)
continue
}
if actualValue != expectedValue {
t.Errorf("Wrong value at environment %s and test %s. Expected: %v, Actual: %v", environment, test, expectedValue, actualValue)
}
}
for test := range expectedTests {
_, testOk := actualTests[test]
if !testOk {
t.Errorf("Missing expected test %s (in environment %s) in actual", test, environment)
}
}
}
for environment := range expectedValues {
_, environmentOk := actualValues[environment]
if !environmentOk {
t.Errorf("Missing expected environment %s in actual", environment)
}
}
}
func TestComputeFlakeRates(t *testing.T) {
actualData := computeFlakeRates(splitEntryMap{
"env1": {
"test1": {
{
name: "test1",
environment: "env1",
date: simpleDate(2000, 4),
status: "Passed",
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 2),
status: "Passed",
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 1),
status: "Failed",
},
},
"test2": {
{
name: "test2",
environment: "env1",
date: simpleDate(2001, 3),
status: "Failed",
}, {
name: "test2",
environment: "env1",
date: simpleDate(2001, 2),
status: "Failed",
}, {
name: "test2",
environment: "env1",
date: simpleDate(2001, 1),
status: "Failed",
},
},
},
"env2": {
"test2": {
{
name: "test2",
environment: "env2",
date: simpleDate(2003, 3),
status: "Passed",
}, testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2003, 2),
status: "Failed",
},
},
},
})
expectedData := map[string]map[string]float32{
"env1": {
"test1": 0.2,
"test2": 1,
},
"env2": {
"test2": 0.5,
},
}
compareValues(t, actualData, expectedData)
}
func TestComputeAverageDurations(t *testing.T) {
actualData := computeAverageDurations(splitEntryMap{
"env1": {
"test1": {
{
name: "test1",
environment: "env1",
date: simpleDate(2000, 4),
status: "Passed",
duration: 1,
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
duration: 2,
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 3),
status: "Passed",
duration: 3,
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 2),
status: "Passed",
duration: 3,
}, {
name: "test1",
environment: "env1",
date: simpleDate(2000, 1),
status: "Failed",
duration: 3,
},
},
"test2": {
{
name: "test2",
environment: "env1",
date: simpleDate(2001, 3),
status: "Failed",
duration: 1,
}, {
name: "test2",
environment: "env1",
date: simpleDate(2001, 2),
status: "Failed",
duration: 3,
}, {
name: "test2",
environment: "env1",
date: simpleDate(2001, 1),
status: "Failed",
duration: 3,
},
},
},
"env2": {
"test2": {
{
name: "test2",
environment: "env2",
date: simpleDate(2003, 3),
status: "Passed",
duration: 0.5,
}, testEntry{
name: "test2",
environment: "env2",
date: simpleDate(2003, 2),
status: "Failed",
duration: 1.5,
},
},
},
})
expectedData := map[string]map[string]float32{
"env1": {
"test1": float32(12) / float32(5),
"test2": float32(7) / float32(3),
},
"env2": {
"test2": 1,
},
}
compareValues(t, actualData, expectedData)
}

View File

@ -0,0 +1,9 @@
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="chart_div"></div>
</body>
<script src="flake_chart.js"></script>
</html>

View File

@ -0,0 +1,194 @@
// Displays an error message to the UI. Any previous message will be erased.
function displayError(message) {
console.error(message);
}
// Creates a generator that reads the response body one line at a time.
async function* bodyByLinesIterator(response) {
// TODO: Replace this with something that actually reads the body line by line
// (since the file can be big).
const lines = (await response.text()).split("\n");
for (let line of lines) {
// Skip any empty lines (most likely at the end).
if (line !== "") {
yield line;
}
}
}
// Determines whether `str` matches at least one value in `enumObject`.
function isValidEnumValue(enumObject, str) {
for (const enumKey in enumObject) {
if (enumObject[enumKey] === str) {
return true;
}
}
return false;
}
// Enum for test status.
const testStatus = {
PASSED: "Passed",
FAILED: "Failed",
SKIPPED: "Skipped"
}
async function loadTestData() {
const response = await fetch("data.csv");
if (!response.ok) {
const responseText = await response.text();
throw `Failed to fetch data from GCS bucket. Error: ${responseText}`;
}
const lines = bodyByLinesIterator(response);
// Consume the header to ensure the data has the right number of fields.
const header = (await lines.next()).value;
if (header.split(",").length != 6) {
throw `Fetched CSV data contains wrong number of fields. Expected: 6. Actual Header: "${header}"`;
}
const testData = [];
let lineData = ["", "", "", "", "", ""];
for await (const line of lines) {
let splitLine = line.split(",");
if (splitLine.length != 6) {
console.warn(`Found line with wrong number of fields. Actual: ${splitLine.length} Expected: 6. Line: "${line}"`);
continue;
}
splitLine = splitLine.map((value, index) => value === "" ? lineData[index] : value);
lineData = splitLine;
if (!isValidEnumValue(testStatus, splitLine[4])) {
console.warn(`Invalid test status provided. Actual: ${splitLine[4]} Expected: One of ${Object.values(testStatus).join(", ")}`);
continue;
}
testData.push({
commit: splitLine[0],
date: new Date(splitLine[1]),
environment: splitLine[2],
name: splitLine[3],
status: splitLine[4],
duration: Number(splitLine[5]),
});
}
if (testData.length == 0) {
throw "Fetched CSV data is empty or poorly formatted.";
}
return testData;
}
// Computes the average of an array of numbers.
Array.prototype.average = function () {
return this.length === 0 ? 0 : this.reduce((sum, value) => sum + value, 0) / this.length;
};
// Groups array elements by keys obtained through `keyGetter`.
Array.prototype.groupBy = function (keyGetter) {
return Array.from(this.reduce((mapCollection, element) => {
const key = keyGetter(element);
if (mapCollection.has(key)) {
mapCollection.get(key).push(element);
} else {
mapCollection.set(key, [element]);
}
return mapCollection;
}, new Map()).values());
};
// Parse URL search `query` into [{key, value}].
function parseUrlQuery(query) {
if (query[0] === '?') {
query = query.substring(1);
}
return Object.fromEntries((query === "" ? [] : query.split("&")).map(element => {
const keyValue = element.split("=");
return [unescape(keyValue[0]), unescape(keyValue[1])];
}));
}
async function init() {
google.charts.load('current', { 'packages': ['corechart'] });
let testData;
try {
// Wait for Google Charts to load, and for test data to load.
// Only store the test data (at index 1) into `testData`.
testData = (await Promise.all([
new Promise(resolve => google.charts.setOnLoadCallback(resolve)),
loadTestData()
]))[1];
} catch (err) {
displayError(err);
return;
}
const data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Flake Percentage');
data.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': true } });
data.addColumn('number', 'Duration');
data.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': true } });
const query = parseUrlQuery(window.location.search);
const desiredTest = query.test || "", desiredEnvironment = query.env || "";
const groups = testData
// Filter to only contain unskipped runs of the requested test and requested environment.
.filter(test => test.name === desiredTest && test.environment === desiredEnvironment && test.status !== testStatus.SKIPPED)
.groupBy(test => test.date.getTime());
data.addRows(
groups
// Sort by run date, past to future.
.sort((a, b) => a[0].date - b[0].date)
// Map each group to all variables need to format the rows.
.map(tests => ({
date: tests[0].date, // Get one of the dates from the tests (which will all be the same).
flakeRate: tests.map(test => test.status === testStatus.FAILED ? 100 : 0).average(), // Compute average of runs where FAILED counts as 100%.
duration: tests.map(test => test.duration).average(), // Compute average duration of runs.
commitHashes: tests.map(test => ({ // Take all hashes, statuses, and durations of tests in this group.
hash: test.commit,
status: test.status,
duration: test.duration
}))
}))
.map(groupData => [
groupData.date,
groupData.flakeRate,
`<div class="py-2 ps-2">
<b>${groupData.date.toString()}</b><br>
<b>Flake Percentage:</b> ${groupData.flakeRate.toFixed(2)}%<br>
<b>Hashes:</b><br>
${groupData.commitHashes.map(({ hash, status }) => ` - ${hash} (${status})`).join("<br>")}
</div>`,
groupData.duration,
`<div class="py-2 ps-2">
<b>${groupData.date.toString()}</b><br>
<b>Average Duration:</b> ${groupData.duration.toFixed(2)}s<br>
<b>Hashes:</b><br>
${groupData.commitHashes.map(({ hash, duration }) => ` - ${hash} (${duration}s)`).join("<br>")}
</div>`,
])
);
const options = {
title: `Flake rate and duration by day of ${desiredTest} on ${desiredEnvironment}`,
width: window.innerWidth,
height: window.innerHeight,
pointSize: 10,
pointShape: "circle",
series: {
0: { targetAxisIndex: 0 },
1: { targetAxisIndex: 1 },
},
vAxes: {
0: { title: "Flake rate", minValue: 0, maxValue: 100 },
1: { title: "Duration (seconds)" },
},
colors: ['#dc3912', '#3366cc'],
tooltip: { trigger: "selection", isHtml: true }
};
const chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
init();

View File

@ -0,0 +1,31 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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.
# Takes a CSV file through stdin, compresses it and writes it to stdout.
# Example usage: < data.csv ./optimize_data.sh > data_optimized.csv
set -eu -o pipefail
# Take input CSV. For each field, if it is the same as the previous row, replace it with an empty string.
# This is to compress the input CSV. Example:
# Input:
# hash,2021-06-10,Docker_Linux,TestFunctional,Passed,0.5
# hash,2021-06-10,Docker_Linux_containerd,TestFunctional,Failed,0.6
#
# Output:
# hash,2021-06-10,Docker_Linux,TestFunctional,Passed,0.5
# ,,DockerLinux_containerd,,Failed,0.6
awk -F, 'BEGIN {OFS = FS} { for(i=1; i<=NF; i++) { if($i == j[i]) { $i = ""; } else { j[i] = $i; } } printf "%s\n",$0 }'

View File

@ -0,0 +1,32 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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.
# Takes a series of gopogh summary jsons, and formats them into a CSV file with
# a row for each test.
# Example usage: cat gopogh_1.json gopogh_2.json gopogh_3.json | ./process_data.sh
set -eu -o pipefail
# Print header.
printf "Commit Hash,Test Date,Environment,Test,Status,Duration\n"
# Turn each test in each summary file to a CSV line containing its commit hash, date, environment, test, status, and duration.
# Example line:
# 247982745892,2021-06-10,Docker_Linux,TestFunctional,Passed,0.5
jq -r '((.PassedTests[]? as $name | {commit: (.Detail.Details | split(":") | .[0]), date: (.Detail.Details | split(":") | .[1]), environment: .Detail.Name, test: $name, duration: .Durations[$name], status: "Passed"}),
(.FailedTests[]? as $name | {commit: (.Detail.Details | split(":") | .[0]), date: (.Detail.Details | split(":") | .[1]), environment: .Detail.Name, test: $name, duration: .Durations[$name], status: "Failed"}),
(.SkippedTests[]? as $name | {commit: (.Detail.Details | split(":") | .[0]), date: (.Detail.Details | split(":") | .[1]), environment: .Detail.Name, test: $name, duration: 0, status: "Skipped"}))
| .commit + "," + .date + "," + .environment + "," + .test + "," + .status + "," + (.duration | tostring)'

View File

@ -0,0 +1,87 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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.
# Creates a comment on the provided PR number, using the provided gopogh summary
# to list out the flake rates of all failing tests.
# Example usage: ./report_flakes.sh 11602 gopogh.json Docker_Linux
set -eu -o pipefail
if [ "$#" -ne 3 ]; then
echo "Wrong number of arguments. Usage: report_flakes.sh <PR number> <gopogh_summary.json> <environment>" 1>&2
exit 1
fi
PR_NUMBER=$1
SUMMARY_DATA=$2
ENVIRONMENT=$3
# To prevent having a super-long comment, add a maximum number of tests to report.
MAX_REPORTED_TESTS=30
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
TMP_DATA=$(mktemp)
# 1) Process the data in the gopogh summary.
# 2) Filter tests to only include failed tests on the environment (and only get their names).
# 3) Sort the names of the tests.
# 4) Store in file $TMP_DATA.
< "$SUMMARY_DATA" $DIR/process_data.sh \
| sed -n -r -e "s/[0-9a-f]*,[0-9-]*,$ENVIRONMENT,([a-zA-Z\/_-]*),Failed,[.0-9]*/\1/p" \
| sort \
> "$TMP_DATA"
# Download the precomputed flake rates from the GCS bucket into file $TMP_FLAKE_RATES.
TMP_FLAKE_RATES=$(mktemp)
gsutil cp gs://minikube-flake-rate/flake_rates.csv "$TMP_FLAKE_RATES"
TMP_FAILED_RATES="$TMP_FLAKE_RATES\_filtered"
# 1) Parse/filter the flake rates to only include the test name and flake rates for environment.
# 2) Sort the flake rates based on test name.
# 3) Join the flake rates with the failing tests to only get flake rates of failing tests.
# 4) Sort failed test flake rates based on the flakiness of that test - stable tests should be first on the list.
# 5) Store in file $TMP_FAILED_RATES.
< "$TMP_FLAKE_RATES" sed -n -r -e "s/$ENVIRONMENT,([a-zA-Z\/_-]*),([.0-9]*),[.0-9]*/\1,\2/p" \
| sort -t, -k1,1 \
| join -t , -j 1 "$TMP_DATA" - \
| sort -g -t, -k2,2 \
> "$TMP_FAILED_RATES"
FAILED_RATES_LINES=$(wc -l < "$TMP_FAILED_RATES")
if [[ "$FAILED_RATES_LINES" -eq 0 ]]; then
echo "No failed tests! Aborting without commenting..." 1>&2
exit 0
fi
# Create the comment template.
TMP_COMMENT=$(mktemp)
printf "These are the flake rates of all failed tests on %s.\n|Failed Tests|Flake Rate (%%)|\n|---|---|\n" "$ENVIRONMENT" > "$TMP_COMMENT"
# 1) Get the first $MAX_REPORTED_TESTS lines.
# 2) Print a row in the table with the test name, flake rate, and a link to the flake chart for that test.
# 3) Append these rows to file $TMP_COMMENT.
< "$TMP_FAILED_RATES" head -n $MAX_REPORTED_TESTS \
| sed -n -r -e "s/([a-zA-Z\/_-]*),([.0-9]*)/|\1|\2 ([chart](https:\/\/storage.googleapis.com\/minikube-flake-rate\/flake_chart.html?env=$ENVIRONMENT\&test=\1))|/p" \
>> "$TMP_COMMENT"
# If there are too many failing tests, add an extra row explaining this, and a message after the table.
if [[ "$FAILED_RATES_LINES" -gt 30 ]]; then
printf "|More tests...|Continued...|\n\nToo many tests failed - See test logs for more details." >> "$TMP_COMMENT"
fi
# install gh if not present
$DIR/../installers/check_install_gh.sh
gh pr comment "https://github.com/kubernetes/minikube/pull/$PR_NUMBER" --body "$(cat $TMP_COMMENT)"

View File

@ -0,0 +1,43 @@
#!/bin/bash
# Copyright 2021 The Kubernetes Authors All rights reserved.
#
# 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.
# Takes a gopogh summary, extracts test data as a CSV and appends to the
# existing CSV data in the GCS bucket.
# Example usage: ./jenkins_upload_tests.sh gopogh_summary.json
set -eu -o pipefail
if [ "$#" -ne 1 ]; then
echo "Wrong number of arguments. Usage: jenkins_upload_tests.sh <gopogh_summary.json>" 1>&2
exit 1
fi
TMP_DATA=$(mktemp)
# Use the gopogh summary, process it, optimize the data, remove the header, and store.
<"$1" ./test-flake-chart/process_data.sh \
| ./test-flake-chart/optimize_data.sh \
| sed "1d" > $TMP_DATA
GCS_TMP="gs://minikube-flake-rate/$(basename "$TMP_DATA")"
# Copy data to append to GCS
gsutil cp $TMP_DATA $GCS_TMP
# Append data to existing data.
gsutil compose gs://minikube-flake-rate/data.csv $GCS_TMP gs://minikube-flake-rate/data.csv
# Clear all the temp stuff.
rm $TMP_DATA
gsutil rm $GCS_TMP

View File

@ -47,3 +47,7 @@ gsutil -qm cp "${HTML_OUT}" "gs://${JOB_GCS_BUCKET}.html" || true
SUMMARY_OUT="$ARTIFACTS/summary.txt"
echo ">> uploading ${SUMMARY_OUT}"
gsutil -qm cp "${SUMMARY_OUT}" "gs://${JOB_GCS_BUCKET}_summary.json" || true
if [[ "${MINIKUBE_LOCATION}" == "master" ]]; then
./test-flake-chart/jenkins_upload_tests.sh "${SUMMARY_OUT}"
fi

View File

@ -70,6 +70,16 @@ var (
`go-version: '.*`: `go-version: '{{.StableVersion}}'`,
},
},
".github/workflows/docs.yml": {
Replace: map[string]string{
`go-version: '.*`: `go-version: '{{.StableVersion}}'`,
},
},
".github/workflows/time-to-k8s.yml": {
Replace: map[string]string{
`go-version: '.*`: `go-version: '{{.StableVersion}}'`,
},
},
".travis.yml": {
Replace: map[string]string{
`go:\n - .*`: `go:{{printf "\n - %s" .StableVersion}}`,

View File

@ -22,6 +22,7 @@ import (
"strings"
"github.com/spf13/viper"
"k8s.io/minikube/deploy/addons"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/out"
@ -79,27 +80,32 @@ func (a *Addon) IsEnabled(cc *config.ClusterConfig) bool {
var Addons = map[string]*Addon{
"auto-pause": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/auto-pause/auto-pause.yaml.tmpl",
addons.AutoPauseAssets,
"auto-pause/auto-pause.yaml.tmpl",
vmpath.GuestAddonsDir,
"auto-pause.yaml",
"0640"),
MustBinAsset(
"deploy/addons/auto-pause/auto-pause-hook.yaml.tmpl",
addons.AutoPauseAssets,
"auto-pause/auto-pause-hook.yaml.tmpl",
vmpath.GuestAddonsDir,
"auto-pause-hook.yaml",
"0640"),
MustBinAsset(
"deploy/addons/auto-pause/haproxy.cfg.tmpl",
addons.AutoPauseAssets,
"auto-pause/haproxy.cfg.tmpl",
vmpath.GuestPersistentDir,
"haproxy.cfg",
"0640"),
MustBinAsset(
"deploy/addons/auto-pause/unpause.lua",
addons.AutoPauseAssets,
"auto-pause/unpause.lua",
vmpath.GuestPersistentDir,
"unpause.lua",
"0640"),
MustBinAsset(
"deploy/addons/auto-pause/auto-pause.service",
addons.AutoPauseAssets,
"auto-pause/auto-pause.service",
"/etc/systemd/system/",
"auto-pause.service",
"0640"),
@ -112,37 +118,37 @@ var Addons = map[string]*Addon{
}),
"dashboard": NewAddon([]*BinAsset{
// We want to create the kubernetes-dashboard ns first so that every subsequent object can be created
MustBinAsset("deploy/addons/dashboard/dashboard-ns.yaml", vmpath.GuestAddonsDir, "dashboard-ns.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-clusterrole.yaml", vmpath.GuestAddonsDir, "dashboard-clusterrole.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-clusterrolebinding.yaml", vmpath.GuestAddonsDir, "dashboard-clusterrolebinding.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-configmap.yaml", vmpath.GuestAddonsDir, "dashboard-configmap.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-dp.yaml.tmpl", vmpath.GuestAddonsDir, "dashboard-dp.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-role.yaml", vmpath.GuestAddonsDir, "dashboard-role.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-rolebinding.yaml", vmpath.GuestAddonsDir, "dashboard-rolebinding.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-sa.yaml", vmpath.GuestAddonsDir, "dashboard-sa.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-secret.yaml", vmpath.GuestAddonsDir, "dashboard-secret.yaml", "0640"),
MustBinAsset("deploy/addons/dashboard/dashboard-svc.yaml", vmpath.GuestAddonsDir, "dashboard-svc.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-ns.yaml", vmpath.GuestAddonsDir, "dashboard-ns.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-clusterrole.yaml", vmpath.GuestAddonsDir, "dashboard-clusterrole.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-clusterrolebinding.yaml", vmpath.GuestAddonsDir, "dashboard-clusterrolebinding.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-configmap.yaml", vmpath.GuestAddonsDir, "dashboard-configmap.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-dp.yaml.tmpl", vmpath.GuestAddonsDir, "dashboard-dp.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-role.yaml", vmpath.GuestAddonsDir, "dashboard-role.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-rolebinding.yaml", vmpath.GuestAddonsDir, "dashboard-rolebinding.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-sa.yaml", vmpath.GuestAddonsDir, "dashboard-sa.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-secret.yaml", vmpath.GuestAddonsDir, "dashboard-secret.yaml", "0640"),
MustBinAsset(addons.DashboardAssets, "dashboard/dashboard-svc.yaml", vmpath.GuestAddonsDir, "dashboard-svc.yaml", "0640"),
}, false, "dashboard", map[string]string{
"Dashboard": "kubernetesui/dashboard:v2.1.0@sha256:7f80b5ba141bead69c4fee8661464857af300d7d7ed0274cf7beecedc00322e6",
"MetricsScraper": "kubernetesui/metrics-scraper:v1.0.4@sha256:555981a24f184420f3be0c79d4efb6c948a85cfce84034f85a563f4151a81cbf",
}, nil),
"default-storageclass": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storageclass/storageclass.yaml.tmpl",
MustBinAsset(addons.DefaultStorageClassAssets,
"storageclass/storageclass.yaml.tmpl",
vmpath.GuestAddonsDir,
"storageclass.yaml",
"0640"),
}, true, "default-storageclass", nil, nil),
"pod-security-policy": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/pod-security-policy/pod-security-policy.yaml.tmpl",
MustBinAsset(addons.PodSecurityPolicyAssets,
"pod-security-policy/pod-security-policy.yaml.tmpl",
vmpath.GuestAddonsDir,
"pod-security-policy.yaml",
"0640"),
}, false, "pod-security-policy", nil, nil),
"storage-provisioner": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storage-provisioner/storage-provisioner.yaml.tmpl",
MustBinAsset(addons.StorageProvisionerAssets,
"storage-provisioner/storage-provisioner.yaml.tmpl",
vmpath.GuestAddonsDir,
"storage-provisioner.yaml",
"0640"),
@ -152,23 +158,23 @@ var Addons = map[string]*Addon{
"StorageProvisioner": "gcr.io",
}),
"storage-provisioner-gluster": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/storage-gluster-ns.yaml.tmpl",
MustBinAsset(addons.StorageProvisionerGlusterAssets,
"storage-provisioner-gluster/storage-gluster-ns.yaml.tmpl",
vmpath.GuestAddonsDir,
"storage-gluster-ns.yaml",
"0640"),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/glusterfs-daemonset.yaml.tmpl",
MustBinAsset(addons.StorageProvisionerGlusterAssets,
"storage-provisioner-gluster/glusterfs-daemonset.yaml.tmpl",
vmpath.GuestAddonsDir,
"glusterfs-daemonset.yaml",
"0640"),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/heketi-deployment.yaml.tmpl",
MustBinAsset(addons.StorageProvisionerGlusterAssets,
"storage-provisioner-gluster/heketi-deployment.yaml.tmpl",
vmpath.GuestAddonsDir,
"heketi-deployment.yaml",
"0640"),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/storage-provisioner-glusterfile.yaml.tmpl",
MustBinAsset(addons.StorageProvisionerGlusterAssets,
"storage-provisioner-gluster/storage-provisioner-glusterfile.yaml.tmpl",
vmpath.GuestAddonsDir,
"storage-privisioner-glusterfile.yaml",
"0640"),
@ -180,33 +186,33 @@ var Addons = map[string]*Addon{
"GlusterfsServer": "quay.io",
}),
"efk": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/efk/elasticsearch-rc.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/elasticsearch-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"elasticsearch-rc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/efk/elasticsearch-svc.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/elasticsearch-svc.yaml.tmpl",
vmpath.GuestAddonsDir,
"elasticsearch-svc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/efk/fluentd-es-rc.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/fluentd-es-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"fluentd-es-rc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/efk/fluentd-es-configmap.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/fluentd-es-configmap.yaml.tmpl",
vmpath.GuestAddonsDir,
"fluentd-es-configmap.yaml",
"0640"),
MustBinAsset(
"deploy/addons/efk/kibana-rc.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/kibana-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"kibana-rc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/efk/kibana-svc.yaml.tmpl",
MustBinAsset(addons.EfkAssets,
"efk/kibana-svc.yaml.tmpl",
vmpath.GuestAddonsDir,
"kibana-svc.yaml",
"0640"),
@ -221,18 +227,18 @@ var Addons = map[string]*Addon{
"Kibana": "docker.elastic.co",
}),
"ingress": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/ingress/ingress-configmap.yaml.tmpl",
MustBinAsset(addons.IngressAssets,
"ingress/ingress-configmap.yaml.tmpl",
vmpath.GuestAddonsDir,
"ingress-configmap.yaml",
"0640"),
MustBinAsset(
"deploy/addons/ingress/ingress-rbac.yaml.tmpl",
MustBinAsset(addons.IngressAssets,
"ingress/ingress-rbac.yaml.tmpl",
vmpath.GuestAddonsDir,
"ingress-rbac.yaml",
"0640"),
MustBinAsset(
"deploy/addons/ingress/ingress-dp.yaml.tmpl",
MustBinAsset(addons.IngressAssets,
"ingress/ingress-dp.yaml.tmpl",
vmpath.GuestAddonsDir,
"ingress-dp.yaml",
"0640"),
@ -244,8 +250,8 @@ var Addons = map[string]*Addon{
"IngressController": "k8s.gcr.io",
}),
"istio-provisioner": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/istio-provisioner/istio-operator.yaml.tmpl",
MustBinAsset(addons.IstioProvisionerAssets,
"istio-provisioner/istio-operator.yaml.tmpl",
vmpath.GuestAddonsDir,
"istio-operator.yaml",
"0640"),
@ -253,15 +259,15 @@ var Addons = map[string]*Addon{
"IstioOperator": "istio/operator:1.5.0@sha256:25a6398ed4996a5313767ceb63768d503c266f63506ad3074b30eef6b5b5167e",
}, nil),
"istio": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/istio/istio-default-profile.yaml.tmpl",
MustBinAsset(addons.IstioAssets,
"istio/istio-default-profile.yaml.tmpl",
vmpath.GuestAddonsDir,
"istio-default-profile.yaml",
"0640"),
}, false, "istio", nil, nil),
"kubevirt": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/kubevirt/pod.yaml.tmpl",
MustBinAsset(addons.KubevirtAssets,
"kubevirt/pod.yaml.tmpl",
vmpath.GuestAddonsDir,
"pod.yaml",
"0640"),
@ -269,23 +275,23 @@ var Addons = map[string]*Addon{
"Kubectl": "bitnami/kubectl:1.17@sha256:de642e973d3d0ef60e4d0a1f92286a9fdae245535c5990d4762bbe86fcf95887",
}, nil),
"metrics-server": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/metrics-server/metrics-apiservice.yaml.tmpl",
MustBinAsset(addons.MetricsServerAssets,
"metrics-server/metrics-apiservice.yaml.tmpl",
vmpath.GuestAddonsDir,
"metrics-apiservice.yaml",
"0640"),
MustBinAsset(
"deploy/addons/metrics-server/metrics-server-deployment.yaml.tmpl",
MustBinAsset(addons.MetricsServerAssets,
"metrics-server/metrics-server-deployment.yaml.tmpl",
vmpath.GuestAddonsDir,
"metrics-server-deployment.yaml",
"0640"),
MustBinAsset(
"deploy/addons/metrics-server/metrics-server-rbac.yaml.tmpl",
MustBinAsset(addons.MetricsServerAssets,
"metrics-server/metrics-server-rbac.yaml.tmpl",
vmpath.GuestAddonsDir,
"metrics-server-rbac.yaml",
"0640"),
MustBinAsset(
"deploy/addons/metrics-server/metrics-server-service.yaml.tmpl",
MustBinAsset(addons.MetricsServerAssets,
"metrics-server/metrics-server-service.yaml.tmpl",
vmpath.GuestAddonsDir,
"metrics-server-service.yaml",
"0640"),
@ -295,13 +301,13 @@ var Addons = map[string]*Addon{
"MetricsServer": "k8s.gcr.io",
}),
"olm": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/olm/crds.yaml.tmpl",
MustBinAsset(addons.OlmAssets,
"olm/crds.yaml.tmpl",
vmpath.GuestAddonsDir,
"crds.yaml",
"0640"),
MustBinAsset(
"deploy/addons/olm/olm.yaml.tmpl",
MustBinAsset(addons.OlmAssets,
"olm/olm.yaml.tmpl",
vmpath.GuestAddonsDir,
"olm.yaml",
"0640"),
@ -313,18 +319,18 @@ var Addons = map[string]*Addon{
"UpstreamCommunityOperators": "quay.io",
}),
"registry": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry/registry-rc.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-rc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry/registry-svc.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-svc.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-svc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry/registry-proxy.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-proxy.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-proxy.yaml",
"0640"),
@ -335,8 +341,8 @@ var Addons = map[string]*Addon{
"KubeRegistryProxy": "gcr.io",
}),
"registry-creds": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry-creds/registry-creds-rc.yaml.tmpl",
MustBinAsset(addons.RegistryCredsAssets,
"registry-creds/registry-creds-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-creds-rc.yaml",
"0640"),
@ -344,28 +350,28 @@ var Addons = map[string]*Addon{
"RegistryCreds": "upmcenterprises/registry-creds:1.10@sha256:93a633d4f2b76a1c66bf19c664dbddc56093a543de6d54320f19f585ccd7d605",
}, nil),
"registry-aliases": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry-aliases/registry-aliases-sa.tmpl",
MustBinAsset(addons.RegistryAliasesAssets,
"registry-aliases/registry-aliases-sa.tmpl",
vmpath.GuestAddonsDir,
"registry-aliases-sa.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry-aliases/registry-aliases-sa-crb.tmpl",
MustBinAsset(addons.RegistryAliasesAssets,
"registry-aliases/registry-aliases-sa-crb.tmpl",
vmpath.GuestAddonsDir,
"registry-aliases-sa-crb.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry-aliases/registry-aliases-config.tmpl",
MustBinAsset(addons.RegistryAliasesAssets,
"registry-aliases/registry-aliases-config.tmpl",
vmpath.GuestAddonsDir,
"registry-aliases-config.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry-aliases/node-etc-hosts-update.tmpl",
MustBinAsset(addons.RegistryAliasesAssets,
"registry-aliases/node-etc-hosts-update.tmpl",
vmpath.GuestAddonsDir,
"node-etc-hosts-update.yaml",
"0640"),
MustBinAsset(
"deploy/addons/registry-aliases/patch-coredns-job.tmpl",
MustBinAsset(addons.RegistryAliasesAssets,
"registry-aliases/patch-coredns-job.tmpl",
vmpath.GuestAddonsDir,
"patch-coredns-job.yaml",
"0640"),
@ -378,8 +384,8 @@ var Addons = map[string]*Addon{
"Pause": "gcr.io",
}),
"freshpod": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/freshpod/freshpod-rc.yaml.tmpl",
MustBinAsset(addons.FreshpodAssets,
"freshpod/freshpod-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"freshpod-rc.yaml",
"0640"),
@ -389,8 +395,8 @@ var Addons = map[string]*Addon{
"FreshPod": "gcr.io",
}),
"nvidia-driver-installer": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gpu/nvidia-driver-installer.yaml.tmpl",
MustBinAsset(addons.NvidiaDriverInstallerAssets,
"gpu/nvidia-driver-installer.yaml.tmpl",
vmpath.GuestAddonsDir,
"nvidia-driver-installer.yaml",
"0640"),
@ -402,8 +408,8 @@ var Addons = map[string]*Addon{
"Pause": "k8s.gcr.io",
}),
"nvidia-gpu-device-plugin": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gpu/nvidia-gpu-device-plugin.yaml.tmpl",
MustBinAsset(addons.NvidiaGpuDevicePluginAssets,
"gpu/nvidia-gpu-device-plugin.yaml.tmpl",
vmpath.GuestAddonsDir,
"nvidia-gpu-device-plugin.yaml",
"0640"),
@ -411,13 +417,13 @@ var Addons = map[string]*Addon{
"NvidiaDevicePlugin": "nvidia/k8s-device-plugin:1.0.0-beta4@sha256:94d46bf513cbc43c4d77a364e4bbd409d32d89c8e686e12551cc3eb27c259b90",
}, nil),
"logviewer": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/logviewer/logviewer-dp-and-svc.yaml.tmpl",
MustBinAsset(addons.LogviewerAssets,
"logviewer/logviewer-dp-and-svc.yaml.tmpl",
vmpath.GuestAddonsDir,
"logviewer-dp-and-svc.yaml",
"0640"),
MustBinAsset(
"deploy/addons/logviewer/logviewer-rbac.yaml.tmpl",
MustBinAsset(addons.LogviewerAssets,
"logviewer/logviewer-rbac.yaml.tmpl",
vmpath.GuestAddonsDir,
"logviewer-rbac.yaml",
"0640"),
@ -425,18 +431,18 @@ var Addons = map[string]*Addon{
"LogViewer": "ivans3/minikube-log-viewer:latest@sha256:75854f45305cc47d17b04c6c588fa60777391761f951e3a34161ddf1f1b06405",
}, nil),
"gvisor": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gvisor/gvisor-pod.yaml.tmpl",
MustBinAsset(addons.GvisorAssets,
"gvisor/gvisor-pod.yaml.tmpl",
vmpath.GuestAddonsDir,
"gvisor-pod.yaml",
"0640"),
MustBinAsset(
"deploy/addons/gvisor/gvisor-runtimeclass.yaml.tmpl",
MustBinAsset(addons.GvisorAssets,
"gvisor/gvisor-runtimeclass.yaml.tmpl",
vmpath.GuestAddonsDir,
"gvisor-runtimeclass.yaml",
"0640"),
MustBinAsset(
"deploy/addons/gvisor/gvisor-config.toml",
MustBinAsset(addons.GvisorAssets,
"gvisor/gvisor-config.toml",
vmpath.GuestGvisorDir,
constants.GvisorConfigTomlTargetName,
"0640"),
@ -446,18 +452,18 @@ var Addons = map[string]*Addon{
"GvisorAddon": "gcr.io",
}),
"helm-tiller": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/helm-tiller/helm-tiller-dp.tmpl",
MustBinAsset(addons.HelmTillerAssets,
"helm-tiller/helm-tiller-dp.tmpl",
vmpath.GuestAddonsDir,
"helm-tiller-dp.yaml",
"0640"),
MustBinAsset(
"deploy/addons/helm-tiller/helm-tiller-rbac.tmpl",
MustBinAsset(addons.HelmTillerAssets,
"helm-tiller/helm-tiller-rbac.tmpl",
vmpath.GuestAddonsDir,
"helm-tiller-rbac.yaml",
"0640"),
MustBinAsset(
"deploy/addons/helm-tiller/helm-tiller-svc.tmpl",
MustBinAsset(addons.HelmTillerAssets,
"helm-tiller/helm-tiller-svc.tmpl",
vmpath.GuestAddonsDir,
"helm-tiller-svc.yaml",
"0640"),
@ -467,8 +473,8 @@ var Addons = map[string]*Addon{
"Tiller": "gcr.io",
}),
"ingress-dns": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/ingress-dns/ingress-dns-pod.yaml.tmpl",
MustBinAsset(addons.IngressDNSAssets,
"ingress-dns/ingress-dns-pod.yaml.tmpl",
vmpath.GuestAddonsDir,
"ingress-dns-pod.yaml",
"0640"),
@ -476,13 +482,13 @@ var Addons = map[string]*Addon{
"IngressDNS": "cryptexlabs/minikube-ingress-dns:0.3.0@sha256:e252d2a4c704027342b303cc563e95d2e71d2a0f1404f55d676390e28d5093ab",
}, nil),
"metallb": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/metallb/metallb.yaml.tmpl",
MustBinAsset(addons.MetallbAssets,
"metallb/metallb.yaml.tmpl",
vmpath.GuestAddonsDir,
"metallb.yaml",
"0640"),
MustBinAsset(
"deploy/addons/metallb/metallb-config.yaml.tmpl",
MustBinAsset(addons.MetallbAssets,
"metallb/metallb-config.yaml.tmpl",
vmpath.GuestAddonsDir,
"metallb-config.yaml",
"0640"),
@ -491,18 +497,18 @@ var Addons = map[string]*Addon{
"Controller": "metallb/controller:v0.9.6@sha256:fbfdb9d3f55976b0ee38f3309d83a4ca703efcf15d6ca7889cd8189142286502",
}, nil),
"ambassador": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/ambassador/ambassador-operator-crds.yaml.tmpl",
MustBinAsset(addons.AmbassadorAssets,
"ambassador/ambassador-operator-crds.yaml.tmpl",
vmpath.GuestAddonsDir,
"ambassador-operator-crds.yaml",
"0640"),
MustBinAsset(
"deploy/addons/ambassador/ambassador-operator.yaml.tmpl",
MustBinAsset(addons.AmbassadorAssets,
"ambassador/ambassador-operator.yaml.tmpl",
vmpath.GuestAddonsDir,
"ambassador-operator.yaml",
"0640"),
MustBinAsset(
"deploy/addons/ambassador/ambassadorinstallation.yaml.tmpl",
MustBinAsset(addons.AmbassadorAssets,
"ambassador/ambassadorinstallation.yaml.tmpl",
vmpath.GuestAddonsDir,
"ambassadorinstallation.yaml",
"0640"),
@ -512,57 +518,57 @@ var Addons = map[string]*Addon{
"AmbassadorOperator": "quay.io",
}),
"gcp-auth": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gcp-auth/gcp-auth-ns.yaml.tmpl",
MustBinAsset(addons.GcpAuthAssets,
"gcp-auth/gcp-auth-ns.yaml.tmpl",
vmpath.GuestAddonsDir,
"gcp-auth-ns.yaml",
"0640"),
MustBinAsset(
"deploy/addons/gcp-auth/gcp-auth-service.yaml.tmpl",
MustBinAsset(addons.GcpAuthAssets,
"gcp-auth/gcp-auth-service.yaml.tmpl",
vmpath.GuestAddonsDir,
"gcp-auth-service.yaml",
"0640"),
MustBinAsset(
"deploy/addons/gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl",
MustBinAsset(addons.GcpAuthAssets,
"gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl",
vmpath.GuestAddonsDir,
"gcp-auth-webhook.yaml",
"0640"),
}, false, "gcp-auth", map[string]string{
"KubeWebhookCertgen": "jettech/kube-webhook-certgen:v1.3.0@sha256:ff01fba91131ed260df3f3793009efbf9686f5a5ce78a85f81c386a4403f7689",
"GCPAuthWebhook": "k8s-minikube/gcp-auth-webhook:v0.0.5@sha256:4da26a6937e876c80642c98fed9efb2269a5d2cb55029de9e2685c9fd6bc1add",
"GCPAuthWebhook": "k8s-minikube/gcp-auth-webhook:v0.0.6@sha256:c407ad6ee97d8a0e8a21c713e2d9af66aaf73315e4a123874c00b786f962f3cd",
}, map[string]string{
"GCPAuthWebhook": "gcr.io",
}),
"volumesnapshots": NewAddon([]*BinAsset{
// make sure the order of apply. `csi-hostpath-snapshotclass` must be the first position, because it depends on `snapshot.storage.k8s.io_volumesnapshotclasses`
// if user disable volumesnapshots addon and delete `csi-hostpath-snapshotclass` after `snapshot.storage.k8s.io_volumesnapshotclasses`, kubernetes will return the error
MustBinAsset(
"deploy/addons/volumesnapshots/csi-hostpath-snapshotclass.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/csi-hostpath-snapshotclass.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-snapshotclass.yaml",
"0640"),
MustBinAsset(
"deploy/addons/volumesnapshots/snapshot.storage.k8s.io_volumesnapshotclasses.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/snapshot.storage.k8s.io_volumesnapshotclasses.yaml.tmpl",
vmpath.GuestAddonsDir,
"snapshot.storage.k8s.io_volumesnapshotclasses.yaml",
"0640"),
MustBinAsset(
"deploy/addons/volumesnapshots/snapshot.storage.k8s.io_volumesnapshotcontents.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/snapshot.storage.k8s.io_volumesnapshotcontents.yaml.tmpl",
vmpath.GuestAddonsDir,
"snapshot.storage.k8s.io_volumesnapshotcontents.yaml",
"0640"),
MustBinAsset(
"deploy/addons/volumesnapshots/snapshot.storage.k8s.io_volumesnapshots.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/snapshot.storage.k8s.io_volumesnapshots.yaml.tmpl",
vmpath.GuestAddonsDir,
"snapshot.storage.k8s.io_volumesnapshots.yaml",
"0640"),
MustBinAsset(
"deploy/addons/volumesnapshots/rbac-volume-snapshot-controller.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/rbac-volume-snapshot-controller.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-volume-snapshot-controller.yaml",
"0640"),
MustBinAsset(
"deploy/addons/volumesnapshots/volume-snapshot-controller-deployment.yaml.tmpl",
MustBinAsset(addons.VolumeSnapshotsAssets,
"volumesnapshots/volume-snapshot-controller-deployment.yaml.tmpl",
vmpath.GuestAddonsDir,
"volume-snapshot-controller-deployment.yaml",
"0640"),
@ -572,68 +578,68 @@ var Addons = map[string]*Addon{
"SnapshotController": "k8s.gcr.io",
}),
"csi-hostpath-driver": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-attacher.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-attacher.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-attacher.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-health-monitor-agent.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-health-monitor-agent.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-health-monitor-agent.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-health-monitor-controller.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-health-monitor-controller.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-health-monitor-controller.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-provisioner.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-provisioner.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-provisioner.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-resizer.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-resizer.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-resizer.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/rbac/rbac-external-snapshotter.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/rbac/rbac-external-snapshotter.yaml.tmpl",
vmpath.GuestAddonsDir,
"rbac-external-snapshotter.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-attacher.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-attacher.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-attacher.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-driverinfo.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-driverinfo.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-driverinfo.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-plugin.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-plugin.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-plugin.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-provisioner.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-provisioner.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-provisioner.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-resizer.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-resizer.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-resizer.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-snapshotter.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-snapshotter.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-snapshotter.yaml",
"0640"),
MustBinAsset(
"deploy/addons/csi-hostpath-driver/deploy/csi-hostpath-storageclass.yaml.tmpl",
MustBinAsset(addons.CsiHostpathDriverAssets,
"csi-hostpath-driver/deploy/csi-hostpath-storageclass.yaml.tmpl",
vmpath.GuestAddonsDir,
"csi-hostpath-storageclass.yaml",
"0640"),

View File

@ -18,6 +18,7 @@ package assets
import (
"bytes"
"embed"
"fmt"
"html/template"
"io"
@ -207,6 +208,7 @@ func NewMemoryAsset(d []byte, targetDir, targetName, permissions string) *Memory
// BinAsset is a bindata (binary data) asset
type BinAsset struct {
embed.FS
BaseAsset
reader io.ReadSeeker
template *template.Template
@ -214,8 +216,8 @@ type BinAsset struct {
}
// MustBinAsset creates a new BinAsset, or panics if invalid
func MustBinAsset(name, targetDir, targetName, permissions string) *BinAsset {
asset, err := NewBinAsset(name, targetDir, targetName, permissions)
func MustBinAsset(fs embed.FS, name, targetDir, targetName, permissions string) *BinAsset {
asset, err := NewBinAsset(fs, name, targetDir, targetName, permissions)
if err != nil {
panic(fmt.Sprintf("Failed to define asset %s: %v", name, err))
}
@ -223,8 +225,9 @@ func MustBinAsset(name, targetDir, targetName, permissions string) *BinAsset {
}
// NewBinAsset creates a new BinAsset
func NewBinAsset(name, targetDir, targetName, permissions string) (*BinAsset, error) {
func NewBinAsset(fs embed.FS, name, targetDir, targetName, permissions string) (*BinAsset, error) {
m := &BinAsset{
FS: fs,
BaseAsset: BaseAsset{
SourcePath: name,
TargetDir: targetDir,
@ -249,7 +252,7 @@ func defaultValue(defValue string, val interface{}) string {
}
func (m *BinAsset) loadData() error {
contents, err := Asset(m.SourcePath)
contents, err := m.FS.ReadFile(m.SourcePath)
if err != nil {
return err
}

View File

@ -248,7 +248,7 @@ func apiServerHealthzNow(hostname string, port int) (state.State, error) {
Proxy: nil, // Avoid using a proxy to speak to a local host
TLSClientConfig: &tls.Config{RootCAs: pool},
}
client := &http.Client{Transport: tr}
client := &http.Client{Transport: tr, Timeout: 5 * time.Second}
resp, err := client.Get(url)
// Connection refused, usually.
if err != nil {

View File

@ -36,20 +36,10 @@ const (
WantBetaUpdateNotification = "WantBetaUpdateNotification"
// ReminderWaitPeriodInHours is the key for ReminderWaitPeriodInHours
ReminderWaitPeriodInHours = "ReminderWaitPeriodInHours"
// WantReportError is the key for WantReportError
WantReportError = "WantReportError"
// WantReportErrorPrompt is the key for WantReportErrorPrompt
WantReportErrorPrompt = "WantReportErrorPrompt"
// WantKubectlDownloadMsg is the key for WantKubectlDownloadMsg
WantKubectlDownloadMsg = "WantKubectlDownloadMsg"
// WantNoneDriverWarning is the key for WantNoneDriverWarning
WantNoneDriverWarning = "WantNoneDriverWarning"
// ProfileName represents the key for the global profile parameter
ProfileName = "profile"
// ShowDriverDeprecationNotification is the key for ShowDriverDeprecationNotification
ShowDriverDeprecationNotification = "ShowDriverDeprecationNotification"
// ShowBootstrapperDeprecationNotification is the key for ShowBootstrapperDeprecationNotification
ShowBootstrapperDeprecationNotification = "ShowBootstrapperDeprecationNotification"
// UserFlag is the key for the global user flag (ex. --user=user1)
UserFlag = "user"
// AddonImages stores custom addon images config
@ -58,6 +48,8 @@ const (
AddonRegistries = "addon-registries"
// AddonListFlag represents the key for addons parameter
AddonListFlag = "addons"
// EmbedCerts represents the config for embedding certificates in kubeconfig
EmbedCerts = "EmbedCerts"
)
var (

View File

@ -131,6 +131,15 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down
}()
for _, img := range append([]string{baseImg}, kic.FallbackImages...) {
var err error
if driver.IsDocker(cc.Driver) {
if download.ImageExistsInDaemon(img) {
klog.Infof("%s exists in daemon, skipping load", img)
finalImg = img
return nil
}
}
klog.Infof("Downloading %s to local cache", img)
err = download.ImageToCache(img)
if err == nil {
@ -141,14 +150,6 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down
return err
}
if driver.IsDocker(cc.Driver) {
if download.ImageExistsInDaemon(img) {
klog.Infof("%s exists in daemon, skipping load", img)
finalImg = img
return nil
}
}
if cc.Driver == driver.Podman {
return fmt.Errorf("not yet implemented, see issue #8426")
}

View File

@ -114,17 +114,12 @@ func Styled(st style.Enum, format string, a ...V) {
}
func boxedCommon(printFunc func(format string, a ...interface{}), format string, a ...V) {
str := Sprintf(style.None, format, a...)
str = strings.TrimSpace(str)
box := box.New(box.Config{Py: 1, Px: 4, Type: "Round"})
if useColor {
box.Config.Color = "Red"
}
str = box.String("", str)
lines := strings.Split(str, "\n")
for _, line := range lines {
printFunc(line + "\n")
}
str := Sprintf(style.None, format, a...)
printFunc(box.String("", strings.TrimSpace(str)))
}
// Boxed writes a stylized and templated message in a box to stdout

View File

@ -19,13 +19,13 @@ package translate
import (
"encoding/json"
"fmt"
"path"
"strings"
"github.com/cloudfoundry-attic/jibber_jabber"
"golang.org/x/text/language"
"k8s.io/klog/v2"
"k8s.io/minikube/translations"
)
var (
@ -69,14 +69,12 @@ func DetermineLocale() {
// Load translations for preferred language into memory.
p := preferredLanguage.String()
translationFile := path.Join("translations", fmt.Sprintf("%s.json", p))
t, err := Asset(translationFile)
t, err := translations.Translations.ReadFile(fmt.Sprintf("%s.json", p))
if err != nil {
// Attempt to find a more broad locale, e.g. fr instead of fr-FR.
if strings.Contains(p, "-") {
p = strings.Split(p, "-")[0]
translationFile := path.Join("translations", fmt.Sprintf("%s.json", p))
t, err = Asset(translationFile)
t, err = translations.Translations.ReadFile(fmt.Sprintf("%s.json", p))
if err != nil {
klog.V(1).Infof("Failed to load translation file for %s: %v", p, err)
return

View File

@ -11,7 +11,7 @@ minikube quickly sets up a local Kubernetes cluster on macOS, Linux, and Windows
![Screenshot](/images/screenshot.png)
🎉 Latest Release: v1.20.0 - May 06, 2021 ([changelog](https://github.com/kubernetes/minikube/blob/master/CHANGELOG.md))
🎉 Latest Release: v1.21.0 - Jun 11, 2021 ([changelog](https://github.com/kubernetes/minikube/blob/master/CHANGELOG.md))
## Highlights

View File

@ -29,19 +29,14 @@ Configurable fields:
* WantUpdateNotification
* WantBetaUpdateNotification
* ReminderWaitPeriodInHours
* WantReportError
* WantReportErrorPrompt
* WantKubectlDownloadMsg
* WantNoneDriverWarning
* profile
* bootstrapper
* ShowDriverDeprecationNotification
* ShowBootstrapperDeprecationNotification
* insecure-registry
* hyperv-virtual-switch
* disable-driver-mounts
* cache
* embed-certs
* EmbedCerts
* native-ssh
```shell

View File

@ -47,24 +47,32 @@ To make the addon appear in `minikube addons list`, add it to `pkg/addons/config
},
```
Next, add all required files using `//go:embed` directives to a new embed.FS variable in `deploy/addons/assets.go`. Here is the entry used by the `csi-hostpath-driver` addon:
```go
// CsiHostpathDriverAssets assets for csi-hostpath-driver addon
//go:embed csi-hostpath-driver/deploy/*.tmpl csi-hostpath-driver/rbac/*.tmpl
CsiHostpathDriverAssets embed.FS
```
Then, add into `pkg/minikube/assets/addons.go` the list of files to copy into the cluster, including manifests. Here is the entry used by the `registry` addon:
```go
"registry": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry/registry-rc.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-rc.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-rc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/registry/registry-svc.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-svc.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/registry/registry-proxy.yaml.tmpl",
MustBinAsset(addons.RegistryAssets,
"registry/registry-proxy.yaml.tmpl",
vmpath.GuestAddonsDir,
"registry-proxy.yaml",
"0640",
@ -74,6 +82,7 @@ Then, add into `pkg/minikube/assets/addons.go` the list of files to copy into th
The `MustBinAsset` arguments are:
* asset variable (typically present in `deploy/addons/assets.go`)
* source filename
* destination directory (typically `vmpath.GuestAddonsDir`)
* destination filename

View File

@ -7,7 +7,7 @@ weight: 2
## Prerequisites
* A recent Go distribution (>=1.12)
* A recent Go distribution (>=1.16)
* If you are on Windows, you'll need Docker to be installed.
* 4GB of RAM

View File

@ -10,7 +10,7 @@ The minikube ISO is booted by each hypervisor to provide a stable minimal Linux
## Prerequisites
* A recent Go distribution (>=1.12)
* A recent Go distribution (>=1.16)
* If you are on Windows, you'll need Docker to be installed.
* 4GB of RAM
* Build tools:

View File

@ -0,0 +1,496 @@
---
title: "v1.21.0 - 2021-06-11"
linkTitle: "v1.21.0 - 2021-06-11"
weight: -97
---
<html>
<head>
<title>kubernetes/minikube - Leaderboard</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" rel="stylesheet">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {packages:["corechart"]});
</script>
<style>
body {
font-family: 'Open Sans', sans-serif;
background-color: #f7f7fa;
padding: 1em;
}
h1 {
color: rgba(66,133,244);
margin-bottom: 0em;
}
.subtitle {
color: rgba(23,90,201);
font-size: small;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
color: #666;
font-size: small;
}
h2.cli {
color: #666;
}
h2 {
color: #333;
}
.board p {
font-size: small;
color: #999;
text-align: center;
}
.board {
clear: right;
display: inline-block;
padding: 0.5em;
margin: 0.5em;
background-color: #fff;
}
.board:nth-child(4n+3) {
border: 2px solid rgba(66,133,244,0.25);
color: rgba(66,133,244);
}
.board:nth-child(4n+2) {
border: 2px solid rgba(219,68,55,0.25);
color: rgba rgba(219,68,55);
}
.board:nth-child(4n+1) {
border: 2px solid rgba(244,160,0,0.25);
color: rgba(244,160,0);
}
.board:nth-child(4n) {
border: 2px solid rgba(15,157,88,0.25);
color: rgba(15,157,88);
}
h3 {
text-align: center;
}
</style>
</head>
<body>
<h1>kubernetes/minikube</h1>
<div class="subtitle">2021-05-06 &mdash; 2021-06-11</div>
<h2>Reviewers</h2>
<div class="board">
<h3>Most Influential</h3>
<p># of Merged PRs reviewed</p>
<div id="chart_reviewCounts" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawreviewCounts);
function drawreviewCounts() {
var data = new google.visualization.arrayToDataTable([
['', '# of Merged PRs reviewed', { role: 'annotation' }],
["medyagh", 46, "46"],
["ilya-zuyev", 6, "6"],
["afbjorklund", 6, "6"],
["sharifelgamal", 5, "5"],
["spowelljr", 4, "4"],
["andriyDev", 2, "2"],
["AkihiroSuda", 1, "1"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_reviewCounts'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Most Helpful</h3>
<p># of words written in merged PRs</p>
<div id="chart_reviewWords" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawreviewWords);
function drawreviewWords() {
var data = new google.visualization.arrayToDataTable([
['', '# of words written in merged PRs', { role: 'annotation' }],
["medyagh", 2911, "2911"],
["afbjorklund", 419, "419"],
["spowelljr", 381, "381"],
["ilya-zuyev", 380, "380"],
["sharifelgamal", 221, "221"],
["andriyDev", 221, "221"],
["AkihiroSuda", 5, "5"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_reviewWords'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Most Demanding</h3>
<p># of Review Comments in merged PRs</p>
<div id="chart_reviewComments" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawreviewComments);
function drawreviewComments() {
var data = new google.visualization.arrayToDataTable([
['', '# of Review Comments in merged PRs', { role: 'annotation' }],
["medyagh", 85, "85"],
["ilya-zuyev", 20, "20"],
["spowelljr", 19, "19"],
["sharifelgamal", 7, "7"],
["afbjorklund", 2, "2"],
["andriyDev", 0, "0"],
["AkihiroSuda", 0, "0"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_reviewComments'));
chart.draw(data, options);
};
</script>
</div>
<h2>Pull Requests</h2>
<div class="board">
<h3>Most Active</h3>
<p># of Pull Requests Merged</p>
<div id="chart_prCounts" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawprCounts);
function drawprCounts() {
var data = new google.visualization.arrayToDataTable([
['', '# of Pull Requests Merged', { role: 'annotation' }],
["spowelljr", 18, "18"],
["afbjorklund", 14, "14"],
["medyagh", 13, "13"],
["andriyDev", 13, "13"],
["ilya-zuyev", 12, "12"],
["sharifelgamal", 11, "11"],
["dinever", 8, "8"],
["daehyeok", 4, "4"],
["guettli", 3, "3"],
["AkihiroSuda", 2, "2"],
["prezha", 2, "2"],
["JacekDuszenko", 2, "2"],
["briandealwis", 2, "2"],
["evankanderson", 1, "1"],
["EmandM", 1, "1"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_prCounts'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Big Movers</h3>
<p>Lines of code (delta)</p>
<div id="chart_prDeltas" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawprDeltas);
function drawprDeltas() {
var data = new google.visualization.arrayToDataTable([
['', 'Lines of code (delta)', { role: 'annotation' }],
["andriyDev", 21210, "21210"],
["sharifelgamal", 2073, "2073"],
["medyagh", 2004, "2004"],
["spowelljr", 955, "955"],
["afbjorklund", 853, "853"],
["daehyeok", 609, "609"],
["ilya-zuyev", 489, "489"],
["dinever", 426, "426"],
["prezha", 276, "276"],
["AkihiroSuda", 91, "91"],
["zhijianli88", 57, "57"],
["guettli", 31, "31"],
["utkarsh-pro", 13, "13"],
["janisz", 12, "12"],
["JacekDuszenko", 11, "11"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_prDeltas'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Most difficult to review</h3>
<p>Average PR size (added+changed)</p>
<div id="chart_prSize" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawprSize);
function drawprSize() {
var data = new google.visualization.arrayToDataTable([
['', 'Average PR size (added+changed)', { role: 'annotation' }],
["andriyDev", 1602, "1602"],
["prezha", 136, "136"],
["medyagh", 130, "130"],
["sharifelgamal", 111, "111"],
["daehyeok", 89, "89"],
["dinever", 42, "42"],
["zhijianli88", 42, "42"],
["spowelljr", 41, "41"],
["afbjorklund", 36, "36"],
["AkihiroSuda", 33, "33"],
["ilya-zuyev", 32, "32"],
["janisz", 11, "11"],
["utkarsh-pro", 8, "8"],
["vigothehacker", 6, "6"],
["guettli", 5, "5"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_prSize'));
chart.draw(data, options);
};
</script>
</div>
<h2>Issues</h2>
<div class="board">
<h3>Most Active</h3>
<p># of comments</p>
<div id="chart_comments" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawcomments);
function drawcomments() {
var data = new google.visualization.arrayToDataTable([
['', '# of comments', { role: 'annotation' }],
["medyagh", 34, "34"],
["afbjorklund", 32, "32"],
["andriyDev", 19, "19"],
["RA489", 16, "16"],
["sharifelgamal", 15, "15"],
["dinever", 14, "14"],
["ilya-zuyev", 12, "12"],
["spowelljr", 8, "8"],
["AkihiroSuda", 8, "8"],
["vishjain", 7, "7"],
["JacekDuszenko", 6, "6"],
["Srikrishnabh", 5, "5"],
["daehyeok", 5, "5"],
["vigothehacker", 5, "5"],
["AlbertMarashi", 5, "5"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_comments'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Most Helpful</h3>
<p># of words (excludes authored)</p>
<div id="chart_commentWords" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawcommentWords);
function drawcommentWords() {
var data = new google.visualization.arrayToDataTable([
['', '# of words (excludes authored)', { role: 'annotation' }],
["Abheestanistala", 3617, "3617"],
["afbjorklund", 1851, "1851"],
["medyagh", 1269, "1269"],
["adamf", 712, "712"],
["dinever", 576, "576"],
["chris-ryu", 539, "539"],
["andriyDev", 532, "532"],
["ilya-zuyev", 487, "487"],
["zhan9san", 352, "352"],
["x3a", 333, "333"],
["AlbertMarashi", 325, "325"],
["sharifelgamal", 276, "276"],
["Srikrishnabh", 265, "265"],
["weshouman", 260, "260"],
["idealism-xxm", 185, "185"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_commentWords'));
chart.draw(data, options);
};
</script>
</div>
<div class="board">
<h3>Top Closers</h3>
<p># of issues closed (excludes authored)</p>
<div id="chart_issueCloser" style="width: 450px; height: 350px;"></div>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawissueCloser);
function drawissueCloser() {
var data = new google.visualization.arrayToDataTable([
['', '# of issues closed (excludes authored)', { role: 'annotation' }],
["medyagh", 40, "40"],
["spowelljr", 23, "23"],
["sharifelgamal", 15, "15"],
["ilya-zuyev", 12, "12"],
["andriyDev", 8, "8"],
["afbjorklund", 3, "3"],
]);
var options = {
axisTitlesPosition: 'none',
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
y: { side: 'top'} // Top x-axis.
}
},
legend: { position: "none" },
bar: { groupWidth: "85%" }
};
var chart = new google.visualization.BarChart(document.getElementById('chart_issueCloser'));
chart.draw(data, options);
};
</script>
</div>
</body>
</html>

View File

@ -130,6 +130,9 @@ asserts that the dashboard command works
#### validateDryRun
asserts that the dry-run mode quickly exits with the right code
#### validateInternationalLanguage
asserts that the language used can be changed with environment variables
#### validateCacheCmd
tests functionality of cache command (cache add, delete, list)

View File

@ -3,14 +3,14 @@ title: "FAQ"
linkTitle: "FAQ"
weight: 3
description: >
Questions that come up regularly
Frequently Asked Questions
---
## How to run an older Kubernetes version with minikube ?
## Can I run an older Kubernetes version with minikube? Do I have to downgrade my minikube version?
You do not need to download an older minikube to run an older kubernetes version.
You can create a Kubenretes cluster with any version you desire using `--kubernetes-version` flag.
You can create a Kubernetes cluster with any version you desire using `--kubernetes-version` flag.
Example:
@ -19,26 +19,27 @@ minikube start --kubernetes-version=v1.15.0
```
## Docker Driver: How to set the cgroup manager minikube uses?
## Docker Driver: How can I set minikube's cgroup manager?
By default minikube uses the `cgroupfs` cgroup manager for the Kubernetes clusters, if you are on a system with a systemd cgroup manager, this could cause conflicts.
To use `systemd` cgroup manager, run:
By default minikube uses the `cgroupfs` cgroup manager for Kubernetes clusters. If you are on a system with a systemd cgroup manager, this could cause conflicts.
To use the `systemd` cgroup manager, run:
```bash
minikube start --force-systemd=true
```
## How to run minikube with Docker driver if existing cluster is VM?
## How can I run minikube with the Docker driver if I have an existing cluster with a VM driver?
If you have an existing cluster with a VM driver (virtualbox, hyperkit, KVM,...).
First please ensure your Docker service is running. Then you need to either:
(a) Delete the existing cluster and create a new one
First please ensure your Docker service is running and then you need to either delete the existing cluster and create one
```bash
minikube delete
minikube start --driver=docker
```
Alternatively, if you want to keep your existing cluster you can create a second cluster with a different profile name. (example p1)
Alternatively, (b) Create a second cluster with a different profile name:
```bash
minikube start -p p1 --driver=docker
@ -46,27 +47,27 @@ minikube start -p p1 --driver=docker
## Does minikube support IPv6?
minikube currently doesn't support IPv6. However, it is on the [roadmap]({{< ref "/docs/contrib/roadmap.en.md" >}}).
minikube currently doesn't support IPv6. However, it is on the [roadmap]({{< ref "/docs/contrib/roadmap.en.md" >}}). You can also refer to the [open issue](https://github.com/kubernetes/minikube/issues/8535).
## How can I prevent password prompts on Linux?
The easiest approach is to use the `docker` driver, as the backend service always runs as `root`.
`none` users may want to try `CHANGE_MINIKUBE_NONE_USER=true`, where kubectl and such will still work: [see environment variables]({{< ref "/docs/handbook/config.md#environment-variables" >}})
`none` users may want to try `CHANGE_MINIKUBE_NONE_USER=true`, where kubectl and such will work without `sudo`. See [environment variables]({{< ref "/docs/handbook/config.md#environment-variables" >}}) for more details.
Alternatively, configure `sudo` to never prompt for the commands issued by minikube.
Alternatively, you can configure `sudo` to never prompt for commands issued by minikube.
## How to ignore system verification?
## How can I ignore system verification?
minikube's bootstrapper, [Kubeadm](https://github.com/kubernetes/kubeadm) verifies a list of features on the host system before installing Kubernetes. in case you get this error, and you still want to try minikube anyways despite your system's limitation you can skip the verification by starting minikube with this extra option:
[kubeadm](https://github.com/kubernetes/kubeadm), minikube's bootstrapper, verifies a list of features on the host system before installing Kubernetes. In the case you get an error and still want to try minikube despite your system's limitation, you can skip verification by starting minikube with this extra option:
```shell
minikube start --extra-config kubeadm.ignore-preflight-errors=SystemVerification
```
## what is the resource allocation for Knative Setup using minikube?
## What is the minimum resource allocation necessary for a Knative setup using minikube?
Please allocate sufficient resources for Knative setup using minikube, especially when you run a minikube cluster on your local machine. We recommend allocating at least 6 CPUs and 8G memory.
Please allocate sufficient resources for Knative setup using minikube, especially when running minikube cluster on your local machine. We recommend allocating at least 6 CPUs and 8G memory:
```shell
minikube start --cpus 6 --memory 8000
@ -74,11 +75,33 @@ minikube start --cpus 6 --memory 8000
## Do I need to install kubectl locally?
No, minikube comes with built-in kubectl [see minikube's kubectl documentation]({{< ref "docs/handbook/kubectl.md" >}}).
No, minikube comes with a built-in kubectl installation. See [minikube's kubectl documentation]({{< ref "docs/handbook/kubectl.md" >}}).
## How to opt-in to beta notifications?
## How can I opt-in to beta release notifications?
Simply run the following command to be enrolled into beta notifications.
Simply run the following command to be enrolled into beta notifications:
```
minikube config set WantBetaUpdateNotification true
```
## Can I get rid of the emoji in minikube's outpuut?
Yes! If you prefer not having emoji in your minikube output 😔 , just set the `MINIKUBE_IN_STYLE` environment variable to `0` or `false`:
```
MINIKUBE_IN_STYLE=0 minikube start
```
## How can I access a minikube cluster from a remote network?
minikube's primary goal is to quickly set up local Kubernetes clusters, and therefore we strongly discourage using minikube in production or for listening to remote traffic. By design, minikube is meant to only listen on the local network.
However, it is possible to configure minikube to listen on a remote network. This will open your network to the outside world and is not recommended. If you are not fully aware of the security implications, please avoid using this.
For the docker and podman driver, use `--listen-address` flag:
```
minikube start --listen-address=0.0.0.0
```

View File

@ -16,7 +16,7 @@ Start a cluster by running:
minikube start
```
Access the Kubernetes Dashboard running within the minikube cluster:
Access the Kubernetes dashboard running within the minikube cluster:
```shell
minikube dashboard

View File

@ -93,6 +93,10 @@ Ask your IT department for the appropriate PEM file, and add it to:
`~/.minikube/files/etc/ssl/certs`
or
`~/.minikube/certs`
Then run `minikube delete` and `minikube start`.
#### downloading binaries: proxyconnect tcp: tls: oversized record received with length 20527

View File

@ -0,0 +1,56 @@
---
title: "Using the User Flag"
linkTitle: "Using the User Flag"
weight: 1
date: 2021-06-15
description: >
Using the User Flag to Keep an Audit Log
---
## Overview
In minikube, all executed commands are logged to a local audit log in the minikube home directory (default: `~/.minikube/logs/audit.json`).
These commands are logged with additional information including the user that ran them, which by default is the OS user.
However, there is a global flag `--user` that will set the user who ran the command in the audit log.
## Prerequisites
- minikube v1.17.1 or newer
## What does the flag do?
Assuming the OS user is `johndoe`, running `minikube start` will add the following to the audit log:
```
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
| Command | Args | Profile | User | Version | Start Time | End Time |
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
| start | | minikube | johndoe | v1.21.0 | Tue, 15 Jun 2021 09:00:00 MST | Tue, 15 Jun 2021 09:01:00 MST |
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
```
As you can see, minikube pulled the OS user and listed them as the user for the command.
Running the same command with `--user=mary` appended to the command will add the following to the audit log:
```
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
| Command | Args | Profile | User | Version | Start Time | End Time |
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
| start | --user=mary | minikube | mary | v1.21.0 | Tue, 15 Jun 2021 09:00:00 MST | Tue, 15 Jun 2021 09:01:00 MST |
|---------------|--------------------------|-----------------------------|--------------|----------------|-------------------------------|-------------------------------|
```
Here you can see that passing `--user=mary` overwrote the OS user with `mary` as the user for the command.
## Example use case
- Embedded use of minikube by multiple users (IDEs, Plugins, etc.)
- A machine shared by multiple users using the same home folder
## How do I use minikube in a script?
If you are using minikube in a script or plugin it is recommeneded to add `--user=your_script_name` to all operations.
Example:
```
minikube start --user=plugin_name
minikube profile list --user=plugin_name
minikube stop --user=plugin_name
```

View File

@ -116,6 +116,7 @@ func TestFunctional(t *testing.T) {
{"ConfigCmd", validateConfigCmd},
{"DashboardCmd", validateDashboardCmd},
{"DryRun", validateDryRun},
{"InternationalLanguage", validateInternationalLanguage},
{"StatusCmd", validateStatusCmd},
{"LogsCmd", validateLogsCmd},
{"LogsFileCmd", validateLogsFileCmd},
@ -897,6 +898,32 @@ func validateDryRun(ctx context.Context, t *testing.T, profile string) {
}
}
// validateInternationalLanguage asserts that the language used can be changed with environment variables
func validateInternationalLanguage(ctx context.Context, t *testing.T, profile string) {
// dry-run mode should always be able to finish quickly (<5s)
mctx, cancel := context.WithTimeout(ctx, Seconds(5))
defer cancel()
// Too little memory!
startArgs := append([]string{"start", "-p", profile, "--dry-run", "--memory", "250MB", "--alsologtostderr"}, StartArgs()...)
c := exec.CommandContext(mctx, Target(), startArgs...)
c.Env = append(os.Environ(), "LC_ALL=fr")
rr, err := Run(t, c)
wantCode := reason.ExInsufficientMemory
if rr.ExitCode != wantCode {
if HyperVDriver() {
t.Skip("skipping this error on HyperV till this issue is solved https://github.com/kubernetes/minikube/issues/9785")
} else {
t.Errorf("dry-run(250MB) exit code = %d, wanted = %d: %v", rr.ExitCode, wantCode, err)
}
}
if !strings.Contains(rr.Stdout.String(), "Utilisation du pilote") {
t.Errorf("dry-run output was expected to be in French. Expected \"Utilisation du pilote\", but not present in output:\n%s", rr.Stdout.String())
}
}
// validateCacheCmd tests functionality of cache command (cache add, delete, list)
func validateCacheCmd(ctx context.Context, t *testing.T, profile string) {
defer PostMortemLogs(t, profile)

View File

@ -625,7 +625,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "Der Name des virtuellen Hyperv-Switch. Standardmäßig zuerst gefunden. (nur Hyperv-Treiber)",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "Die von der minikube-VM verwendete Kubernetes-Version (Beispiel: v1.2.3)",

View File

@ -630,7 +630,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "El nombre del conmutador virtual de hyperv. El valor predeterminado será el primer nombre que se encuentre (solo con el controlador de hyperv).",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "La versión de Kubernetes que utilizará la VM de minikube (p. ej.: versión 1.2.3)",

View File

@ -628,7 +628,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "Nom du commutateur virtuel hyperv. La valeur par défaut affiche le premier commutateur trouvé (pilote hyperv uniquement).",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "Version de Kubernetes qu'utilisera la VM minikube (exemple : v1.2.3).",

View File

@ -624,7 +624,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "hyperv 仮想スイッチ名。最初に見つかったものにデフォルト設定されますhyperv ドライバのみ)",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "minikube VM で使用される Kubernetes バージョン(例: v1.2.3",

View File

@ -33,8 +33,7 @@
"A set of apiserver IP Addresses which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "",
"A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "",
"A set of key=value pairs that describe feature gates for alpha/experimental features.": "",
"Access the Kubernetes dashboard running within the minikube cluster": "",
"Access the kubernetes dashboard running within the minikube cluster": "minikube 클러스터 내의 쿠버네티스 대시보드에 접근합니다",
"Access the Kubernetes dashboard running within the minikube cluster": "minikube 클러스터 내의 쿠버네티스 대시보드에 접근합니다",
"Access to ports below 1024 may fail on Windows with OpenSSH clients older than v8.1. For more information, see: https://minikube.sigs.k8s.io/docs/handbook/accessing/#access-to-ports-1024-on-windows-requires-root-permission": "",
"Add SSH identity key to SSH authentication agent": "SSH 인증 에이전트에 SSH ID 키 추가합니다",
"Add an image to local cache.": "로컬 캐시에 이미지를 추가합니다",
@ -639,7 +638,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The machine-driver specified is failing to start. Try running 'docker-machine-driver-\u003ctype\u003e version'": "",

View File

@ -32,8 +32,7 @@
"A set of apiserver IP Addresses which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "",
"A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "",
"A set of key=value pairs that describe feature gates for alpha/experimental features.": "",
"Access the Kubernetes dashboard running within the minikube cluster": "",
"Access the kubernetes dashboard running within the minikube cluster": "Dostęp do dashboardu uruchomionego w klastrze kubernetesa w minikube",
"Access the Kubernetes dashboard running within the minikube cluster": "Dostęp do dashboardu uruchomionego w klastrze kubernetesa w minikube",
"Access to ports below 1024 may fail on Windows with OpenSSH clients older than v8.1. For more information, see: https://minikube.sigs.k8s.io/docs/handbook/accessing/#access-to-ports-1024-on-windows-requires-root-permission": "",
"Add SSH identity key to SSH authentication agent": "",
"Add an image to local cache.": "Dodaj obraz do lokalnego cache",
@ -643,7 +642,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "Wersja kubernetesa, która zostanie użyta przez wirtualną maszynę minikube (np. v1.2.3)",

View File

@ -585,7 +585,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The machine-driver specified is failing to start. Try running 'docker-machine-driver-\u003ctype\u003e version'": "",

View File

@ -0,0 +1,23 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package translations
import "embed"
// Translations contains all translation JSON files.
//go:embed *.json
var Translations embed.FS

View File

@ -39,8 +39,7 @@
"A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine": "一组在为 kubernetes 生成的证书中使用的 apiserver 名称。如果您希望将此 apiserver 设置为可从机器外部访问,则可以使用这组 apiserver 名称",
"A set of key=value pairs that describe configuration that may be passed to different components.\nThe key should be '.' separated, and the first part before the dot is the component to apply the configuration to.\nValid components are: kubelet, kubeadm, apiserver, controller-manager, etcd, proxy, scheduler\nValid kubeadm parameters:": "一组用于描述可传递给不同组件的配置的键值对。\n其中键应以英文句点“.”分隔,英文句点前面的第一个部分是应用该配置的组件。\n有效组件包括kubelet、kubeadm、apiserver、controller-manager、etcd、proxy、scheduler\n有效 kubeadm 参数包括:",
"A set of key=value pairs that describe feature gates for alpha/experimental features.": "一组用于描述 alpha 版功能/实验性功能的功能限制的键值对。",
"Access the Kubernetes dashboard running within the minikube cluster": "",
"Access the kubernetes dashboard running within the minikube cluster": "访问在 minikube 集群中运行的 kubernetes dashboard",
"Access the Kubernetes dashboard running within the minikube cluster": "访问在 minikube 集群中运行的 kubernetes dashboard",
"Access to ports below 1024 may fail on Windows with OpenSSH clients older than v8.1. For more information, see: https://minikube.sigs.k8s.io/docs/handbook/accessing/#access-to-ports-1024-on-windows-requires-root-permission": "",
"Add SSH identity key to SSH authentication agent": "",
"Add an image to local cache.": "将 image 添加到本地缓存。",
@ -732,7 +731,7 @@
"The heapster addon is depreciated. please try to disable metrics-server instead": "",
"The hyperv virtual switch name. Defaults to first found. (hyperv driver only)": "hyperv 虚拟交换机名称。默认为找到的第一个 hyperv 虚拟交换机。(仅限 hyperv 驱动程序)",
"The hypervisor does not appear to be configured properly. Run 'minikube start --alsologtostderr -v=1' and inspect the error code": "管理程序似乎配置的不正确。执行 'minikube start --alsologtostderr -v=1' 并且检查错误代码",
"The image you are trying to add {{.imageName}} doesn't exist!": "",
"The image '{{.imageName}}' was not found; unable to add it to cache.": "",
"The initial time interval for each check that wait performs in seconds": "",
"The kubeadm binary within the Docker container is not executable": "",
"The kubernetes version that the minikube VM will use (ex: v1.2.3)": "minikube 虚拟机将使用的 kubernetes 版本(例如 v1.2.3",