Merge branch 'master' into 2020-roadmap-planning

pull/5452/head
tstromberg 2019-11-06 12:19:56 -08:00
commit b33bb0fcc2
309 changed files with 12182 additions and 3280 deletions

View File

@ -1 +1,7 @@
comment: false
comment:
layout: "reach, diff, flags, files"
behavior: default
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
branches: null # branch names that can post comment

8
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,8 @@
<!-- 🎉 Thank you for contributing to minikube! 🎉 Here are some hints to get your PR merged faster:
1. Your PR title will be included in the release notes, choose it carefully
2. If the PR fixes an issue, add "fixes #<issue number>" to the description.
3. If the PR is a user interface change, please include a "before" and "after" example.
4. If the PR is a large design change, please include an enhancement proposal:
https://github.com/kubernetes/minikube/tree/master/enhancements
-->

1
.gitignore vendored
View File

@ -32,6 +32,7 @@ _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

View File

@ -1,23 +1,45 @@
language: go
---
# linted with yamllint
os: linux
language: go
go:
- 1.12.12
env:
- GOPROXY=https://proxy.golang.org
global:
- GOPROXY=https://proxy.golang.org
matrix:
include:
- go: 1.12.9
- language: python
before_install: pip install flake8
script: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- language: go
name: Code Lint
go: 1.12.12
env:
- TESTSUITE=lintall
before_install:
- sudo apt-get install -y libvirt-dev
script: make test
before_install:
- sudo apt-get install -y libvirt-dev
install:
- echo "Don't run anything."
script:
- make test
- language: go
name: Unit Test
go: 1.12.12
env:
- TESTSUITE=unittest
before_install:
- sudo apt-get install -y libvirt-dev
script: make test
- language: go
name: Build
go: 1.12.12
script: make
after_success:
- bash <(curl -s https://codecov.io/bash)
travisBuddy:
regex: (FAIL:|\.go:\d+:|^panic:|failed$)
notifications:
webhooks: https://www.travisbuddy.com/
on_success: never # travisbuddy don't comment on successfull
webhooks:
urls:
- https://www.travisbuddy.com?only=failed,errored
on_success: never # don't comment on successful builds.
on_failure: always
on_cancel: always
on_error: always

View File

@ -1,5 +1,121 @@
# Release Notes
## Version 1.5.2 - 2019-10-31 (Happy Halloween!)
* service: fix --url mode [#5790](https://github.com/kubernetes/minikube/pull/5790)
* Refactor command runner interface, allow stdin writes [#5530](https://github.com/kubernetes/minikube/pull/5530)
* macOS install docs: minikube is a normal Homebrew formula now [#5750](https://github.com/kubernetes/minikube/pull/5750)
* Allow CPU count check to be disabled using --force [#5803](https://github.com/kubernetes/minikube/pull/5803)
* Make network validation friendlier, especially to corp networks [#5802](https://github.com/kubernetes/minikube/pull/5802)
Thank you to our contributors for this release:
- Anders F Björklund
- Issy Long
- Medya Ghazizadeh
- Thomas Strömberg
## Version 1.5.1 - 2019-10-29
* Set Docker open-files limit ( 'ulimit -n') to be consistent with other runtimes [#5761](https://github.com/kubernetes/minikube/pull/5761)
* Use fixed uid/gid for the default user account [#5767](https://github.com/kubernetes/minikube/pull/5767)
* Set --wait=false to default but still wait for apiserver [#5757](https://github.com/kubernetes/minikube/pull/5757)
* kubelet: Pass --config to use kubeadm generated configuration [#5697](https://github.com/kubernetes/minikube/pull/5697)
* Refactor to remove opening browser and just return url(s) [#5718](https://github.com/kubernetes/minikube/pull/5718)
Huge thank you for this release towards our contributors:
- Anders F Björklund
- Medya Ghazizadeh
- Nanik T
- Priya Wadhwa
- Sharif Elgamal
- Thomas Strömberg
## Version 1.5.0 - 2019-10-25
* Default to best-available local hypervisor rather than VirtualBox [#5700](https://github.com/kubernetes/minikube/pull/5700)
* Update default Kubernetes version to v1.16.2 [#5731](https://github.com/kubernetes/minikube/pull/5731)
* Add json output for status [#5611](https://github.com/kubernetes/minikube/pull/5611)
* gvisor: Use chroot instead of LD_LIBRARY_PATH [#5735](https://github.com/kubernetes/minikube/pull/5735)
* Hide innocuous viper ConfigFileNotFoundError [#5732](https://github.com/kubernetes/minikube/pull/5732)
Thank you to our contributors!
- Anders F Björklund
- duohedron
- Javis Zhou
- Josh Woodcock
- Kenta Iso
- Marek Schwarz
- Medya Ghazizadeh
- Nanik T
- Rob Bruce
- Sharif Elgamal
- Thomas Strömberg
## Version 1.5.0-beta.0 - 2019-10-21
* Fix node InternalIP not matching host-only address [#5427](https://github.com/kubernetes/minikube/pull/5427)
* Add helm-tiller addon [#5363](https://github.com/kubernetes/minikube/pull/5363)
* Add ingress-dns addon [#5507](https://github.com/kubernetes/minikube/pull/5507)
* Add validation checking for minikube profile [#5624](https://github.com/kubernetes/minikube/pull/5624)
* add ability to override autoupdating drivers [#5640](https://github.com/kubernetes/minikube/pull/5640)
* Add option to configure dnsDomain in kubeAdm [#5566](https://github.com/kubernetes/minikube/pull/5566)
* Added flags to purge configuration with minikube delete [#5548](https://github.com/kubernetes/minikube/pull/5548)
* Upgrade Buildroot to 2019.02 and VirtualBox to 5.2 [#5609](https://github.com/kubernetes/minikube/pull/5609)
* Add libmachine debug logs back [#5574](https://github.com/kubernetes/minikube/pull/5574)
* Add JSON output for addons list [#5601](https://github.com/kubernetes/minikube/pull/5601)
* Update default Kubernetes version to 1.16.1 [#5593](https://github.com/kubernetes/minikube/pull/5593)
* Upgrade nginx ingress controller to 0.26.1 [#5514](https://github.com/kubernetes/minikube/pull/5514)
* Initial translations for fr, es, de, ja, and zh-CN [#5466](https://github.com/kubernetes/minikube/pull/5466)
* PL translation [#5491](https://github.com/kubernetes/minikube/pull/5491)
* Warn if incompatible kubectl version is in use [#5596](https://github.com/kubernetes/minikube/pull/5596)
* Fix crash when deleting the cluster but it doesn't exist [#4980](https://github.com/kubernetes/minikube/pull/4980)
* Add json output for profile list [#5554](https://github.com/kubernetes/minikube/pull/5554)
* Allow addon enabling and disabling when minikube is not running [#5565](https://github.com/kubernetes/minikube/pull/5565)
* Added option to delete all profiles [#4780](https://github.com/kubernetes/minikube/pull/4780)
* Replace registry-creds addon ReplicationController with Deployment [#5586](https://github.com/kubernetes/minikube/pull/5586)
* Performance and security enhancement for ingress-dns addon [#5614](https://github.com/kubernetes/minikube/pull/5614)
* Add addons flag to 'minikube start' in order to enable specified addons [#5543](https://github.com/kubernetes/minikube/pull/5543)
* Warn when a user tries to set a profile name that is unlikely to be valid [#4999](https://github.com/kubernetes/minikube/pull/4999)
* Make error message more human readable [#5563](https://github.com/kubernetes/minikube/pull/5563)
* Adjusted Terminal Style Detection [#5508](https://github.com/kubernetes/minikube/pull/5508)
* Fixes image repository flags when using CRI-O and containerd runtime [#5447](https://github.com/kubernetes/minikube/pull/5447)
* fix "minikube update-context" command fail [#5626](https://github.com/kubernetes/minikube/pull/5626)
* Fix pods not being scheduled when ingress deployment is patched [#5519](https://github.com/kubernetes/minikube/pull/5519)
* Fix order of parameters to CurrentContext funcs [#5439](https://github.com/kubernetes/minikube/pull/5439)
* Add solution for VERR_VMX_MSR_ALL_VMX_DISABLED [#5460](https://github.com/kubernetes/minikube/pull/5460)
* fr: fix translations of environment & existent [#5483](https://github.com/kubernetes/minikube/pull/5483)
* optimizing Chinese translation [#5201](https://github.com/kubernetes/minikube/pull/5201)
* Change systemd unit files perm to 644 [#5492](https://github.com/kubernetes/minikube/pull/5492)
Huge thank you for this release towards our contributors:
- Anders F Björklund
- bhanu011
- chentanjun
- Cornelius Weig
- Doug A
- hwdef
- James Peach
- Josh Woodcock
- Kenta Iso
- Marcin Niemira
- Medya Ghazizadeh
- Nanik T
- Pranav Jituri
- Samuel Almeida
- serhatcetinkaya
- Sharif Elgamal
- tanjunchen
- Thomas Strömberg
- u5surf
- yugo horie
- yuxiaobo
- Zhongcheng Lao
- Zoltán Reegn
## Version 1.4.0 - 2019-09-17
Notable user-facing changes:
@ -784,7 +900,7 @@ Huge thank you for this release towards our contributors:
* Issue #3037 change dependency management to dep [#3136](https://github.com/kubernetes/minikube/pull/3136)
* Update dashboard version to v1.10.0 [#3122](https://github.com/kubernetes/minikube/pull/3122)
* fix: --format outputs any string, --https only subsitute http URL scheme [#3114](https://github.com/kubernetes/minikube/pull/3114)
* fix: --format outputs any string, --https only substitute http URL scheme [#3114](https://github.com/kubernetes/minikube/pull/3114)
* Change default docker storage driver to overlay2 [#3121](https://github.com/kubernetes/minikube/pull/3121)
* Add env variable for default ES_JAVA_OPTS [#3086](https://github.com/kubernetes/minikube/pull/3086)
* fix(cli): `minikube start --mount --mountsting` without write permission [#2671](https://github.com/kubernetes/minikube/pull/2671)

109
Makefile
View File

@ -14,22 +14,22 @@
# Bump these on release - and please check ISO_VERSION for correctness.
VERSION_MAJOR ?= 1
VERSION_MINOR ?= 4
VERSION_BUILD ?= 0
VERSION_MINOR ?= 5
VERSION_BUILD ?= 2
RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).${VERSION_BUILD}
VERSION ?= v$(RAW_VERSION)
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).0
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).1
# Dashes are valid in semver, but not Linux packaging. Use ~ to delimit alpha/beta
DEB_VERSION ?= $(subst -,~,$(RAW_VERSION))
RPM_VERSION ?= $(DEB_VERSION)
# used by hack/jenkins/release_build_and_upload.sh and KVM_BUILD_IMAGE, see also BUILD_IMAGE below
GO_VERSION ?= 1.12.9
GO_VERSION ?= 1.12.12
INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1)
BUILDROOT_BRANCH ?= 2018.05.3
BUILDROOT_BRANCH ?= 2019.02.6
REGISTRY?=gcr.io/k8s-minikube
# Get git commit id
@ -49,19 +49,21 @@ MINIKUBE_BUCKET ?= minikube/releases
MINIKUBE_UPLOAD_LOCATION := gs://${MINIKUBE_BUCKET}
MINIKUBE_RELEASES_URL=https://github.com/kubernetes/minikube/releases/download
KERNEL_VERSION ?= 4.15
KERNEL_VERSION ?= 4.19.76
# latest from https://github.com/golangci/golangci-lint/releases
GOLINT_VERSION ?= v1.18.0
GOLINT_VERSION ?= v1.21.0
# Limit number of default jobs, to avoid the CI builds running out of memory
GOLINT_JOBS ?= 4
# see https://github.com/golangci/golangci-lint#memory-usage-of-golangci-lint
GOLINT_GOGC ?= 8
GOLINT_GOGC ?= 100
# options for lint (golangci-lint)
GOLINT_OPTIONS = --deadline 4m \
GOLINT_OPTIONS = --timeout 4m \
--build-tags "${MINIKUBE_INTEGRATION_BUILD_TAGS}" \
--enable goimports,gocritic,golint,gocyclo,interfacer,misspell,nakedret,stylecheck,unconvert,unparam \
--enable goimports,gocritic,golint,gocyclo,misspell,nakedret,stylecheck,unconvert,unparam,dogsled \
--exclude 'variable on range scope.*in function literal|ifElseChain'
# Major version of gvisor image. Increment when there are breaking changes.
GVISOR_IMAGE_VERSION ?= 2
export GO111MODULE := on
@ -97,6 +99,7 @@ MARKDOWNLINT ?= markdownlint
MINIKUBE_MARKDOWN_FILES := README.md docs CONTRIBUTING.md CHANGELOG.md
MINIKUBE_BUILD_TAGS := container_image_ostree_stub containers_image_openpgp
MINIKUBE_BUILD_TAGS += go_getter_nos3 go_getter_nogcs
MINIKUBE_INTEGRATION_BUILD_TAGS := integration $(MINIKUBE_BUILD_TAGS)
CMD_SOURCE_DIRS = cmd pkg
@ -127,6 +130,12 @@ endif
ifeq ($(GOOS),windows)
IS_EXE = .exe
DIRSEP_ = \\
DIRSEP = $(strip $(DIRSEP_))
PATHSEP = ;
else
DIRSEP = /
PATHSEP = :
endif
@ -136,8 +145,15 @@ out/minikube$(IS_EXE): out/minikube-$(GOOS)-$(GOARCH)$(IS_EXE)
out/minikube-windows-amd64.exe: out/minikube-windows-amd64
cp $< $@
.PHONY: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe
out/minikube-linux-x86_64: out/minikube-linux-amd64
cp $< $@
out/minikube-linux-aarch64: out/minikube-linux-arm64
cp $< $@
.PHONY: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe
minikube-linux-amd64: out/minikube-linux-amd64
minikube-linux-arm64: out/minikube-linux-arm64
minikube-darwin-amd64: out/minikube-darwin-amd64
minikube-windows-amd64.exe: out/minikube-windows-amd64.exe
@ -239,33 +255,27 @@ extract:
pkg/minikube/assets/assets.go: $(shell find "deploy/addons" -type f)
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
else ifeq ($(GOOS),windows)
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
-gofmt -s -w $@
else
which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
-gofmt -s -w $@
endif
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
-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
pkg/minikube/translate/translations.go: $(shell find "translations/" -type f)
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
else ifeq ($(GOOS),windows)
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
-gofmt -s -w $@
else
which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
-gofmt -s -w $@
endif
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
-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
cross: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe
.PHONY: windows
windows: minikube-windows-amd64.exe
@ -281,7 +291,8 @@ e2e-cross: e2e-linux-amd64 e2e-darwin-amd64 e2e-windows-amd64.exe
.PHONY: checksum
checksum:
for f in out/minikube-linux-amd64 out/minikube-darwin-amd64 out/minikube-windows-amd64.exe out/minikube.iso \
for f in out/minikube.iso out/minikube-linux-amd64 minikube-linux-arm64 \
out/minikube-darwin-amd64 out/minikube-windows-amd64.exe \
out/docker-machine-driver-kvm2 out/docker-machine-driver-hyperkit; do \
if [ -f "$${f}" ]; then \
openssl sha256 "$${f}" | awk '{print $$2}' > "$${f}.sha256" ; \
@ -312,7 +323,7 @@ vet:
@go vet $(SOURCE_PACKAGES)
.PHONY: golint
golint:
golint: pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go
@golint -set_exit_status $(SOURCE_PACKAGES)
.PHONY: gocyclo
@ -348,21 +359,29 @@ mdlint:
out/docs/minikube.md: $(shell find "cmd") $(shell find "pkg/minikube/constants") pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go
go run -ldflags="$(MINIKUBE_LDFLAGS)" -tags gendocs hack/help_text/gen_help_text.go
out/minikube_$(DEB_VERSION).deb: out/minikube-linux-amd64
out/minikube_$(DEB_VERSION).deb: out/minikube_$(DEB_VERSION)-0_amd64.deb
cp $< $@
out/minikube_$(DEB_VERSION)-0_%.deb: out/minikube-linux-%
cp -r installers/linux/deb/minikube_deb_template out/minikube_$(DEB_VERSION)
chmod 0755 out/minikube_$(DEB_VERSION)/DEBIAN
sed -E -i 's/--VERSION--/'$(DEB_VERSION)'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control
sed -E -i 's/--ARCH--/'$*'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control
mkdir -p out/minikube_$(DEB_VERSION)/usr/bin
cp out/minikube-linux-amd64 out/minikube_$(DEB_VERSION)/usr/bin/minikube
fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION)
cp $< out/minikube_$(DEB_VERSION)/usr/bin/minikube
fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION) $@
rm -rf out/minikube_$(DEB_VERSION)
out/minikube-$(RPM_VERSION).rpm: out/minikube-linux-amd64
out/minikube-$(RPM_VERSION).rpm: out/minikube-$(RPM_VERSION)-0.x86_64.rpm
cp $< $@
out/minikube-$(RPM_VERSION)-0.%.rpm: out/minikube-linux-%
cp -r installers/linux/rpm/minikube_rpm_template out/minikube-$(RPM_VERSION)
sed -E -i 's/--VERSION--/'$(RPM_VERSION)'/g' out/minikube-$(RPM_VERSION)/minikube.spec
sed -E -i 's|--OUT--|'$(PWD)/out'|g' out/minikube-$(RPM_VERSION)/minikube.spec
rpmbuild -bb -D "_rpmdir $(PWD)/out" -D "_rpmfilename minikube-$(RPM_VERSION).rpm" \
rpmbuild -bb -D "_rpmdir $(PWD)/out" --target $* \
out/minikube-$(RPM_VERSION)/minikube.spec
@mv out/$*/minikube-$(RPM_VERSION)-0.$*.rpm out/ && rmdir out/$*
rm -rf out/minikube-$(RPM_VERSION)
.PHONY: apt
@ -380,14 +399,16 @@ out/repodata/repomd.xml: out/minikube-$(RPM_VERSION).rpm
-u "$(MINIKUBE_RELEASES_URL)/$(VERSION)/" out
.SECONDEXPANSION:
TAR_TARGETS_linux := out/minikube-linux-amd64 out/docker-machine-driver-kvm2
TAR_TARGETS_darwin := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit
TAR_TARGETS_windows := out/minikube-windows-amd64.exe
out/minikube-%-amd64.tar.gz: $$(TAR_TARGETS_$$*)
TAR_TARGETS_linux-amd64 := out/minikube-linux-amd64 out/docker-machine-driver-kvm2
TAR_TARGETS_linux-arm64 := out/minikube-linux-arm64
TAR_TARGETS_darwin-amd64 := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit
TAR_TARGETS_windows-amd64 := out/minikube-windows-amd64.exe
out/minikube-%.tar.gz: $$(TAR_TARGETS_$$*)
tar -cvzf $@ $^
.PHONY: cross-tars
cross-tars: out/minikube-windows-amd64.tar.gz out/minikube-linux-amd64.tar.gz out/minikube-darwin-amd64.tar.gz
cross-tars: out/minikube-linux-amd64.tar.gz out/minikube-linux-arm64.tar.gz \
out/minikube-windows-amd64.tar.gz out/minikube-darwin-amd64.tar.gz
-cd out && $(SHA512SUM) *.tar.gz > SHA512SUM
out/minikube-installer.exe: out/minikube-windows-amd64.exe
@ -464,11 +485,11 @@ out/gvisor-addon: pkg/minikube/assets/assets.go pkg/minikube/translate/translati
.PHONY: gvisor-addon-image
gvisor-addon-image: out/gvisor-addon
docker build -t $(REGISTRY)/gvisor-addon:latest -f deploy/gvisor/Dockerfile .
docker build -t $(REGISTRY)/gvisor-addon:$(GVISOR_IMAGE_VERSION) -f deploy/gvisor/Dockerfile .
.PHONY: push-gvisor-addon-image
push-gvisor-addon-image: gvisor-addon-image
gcloud docker -- push $(REGISTRY)/gvisor-addon:latest
gcloud docker -- push $(REGISTRY)/gvisor-addon:$(GVISOR_IMAGE_VERSION)
.PHONY: release-iso
release-iso: minikube_iso checksum
@ -551,3 +572,7 @@ site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo
--navigateToChanged \
--ignoreCache \
--buildFuture)
.PHONY: out/mkcmp
out/mkcmp:
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/main.go

4
OWNERS
View File

@ -7,12 +7,16 @@ reviewers:
- RA489
- medyagh
- josedonizetti
- blueelvis
- priyawadhwa
approvers:
- tstromberg
- afbjorklund
- sharifelgamal
- RA489
- medyagh
- josedonizetti
- priyawadhwa
emeritus_approvers:
- dlorenc
- luxas

View File

@ -22,9 +22,13 @@ import (
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/machine"
)
// cacheImageConfigKey is the config field name used to store which images we have previously cached
const cacheImageConfigKey = "cache"
// cacheCmd represents the cache command
var cacheCmd = &cobra.Command{
Use: "cache",
@ -43,7 +47,7 @@ var addCacheCmd = &cobra.Command{
exit.WithError("Failed to cache and load images", err)
}
// Add images to config file
if err := cmdConfig.AddToConfigMap(constants.Cache, args); err != nil {
if err := cmdConfig.AddToConfigMap(cacheImageConfigKey, args); err != nil {
exit.WithError("Failed to update config", err)
}
},
@ -56,7 +60,7 @@ var deleteCacheCmd = &cobra.Command{
Long: "Delete an image from the local cache.",
Run: func(cmd *cobra.Command, args []string) {
// Delete images from config file
if err := cmdConfig.DeleteFromConfigMap(constants.Cache, args); err != nil {
if err := cmdConfig.DeleteFromConfigMap(cacheImageConfigKey, args); err != nil {
exit.WithError("Failed to delete images from config", err)
}
// Delete images from cache/images directory
@ -67,11 +71,11 @@ var deleteCacheCmd = &cobra.Command{
}
func imagesInConfigFile() ([]string, error) {
configFile, err := config.ReadConfig(constants.ConfigFile)
configFile, err := config.ReadConfig(localpath.ConfigFile)
if err != nil {
return nil, err
}
if values, ok := configFile[constants.Cache]; ok {
if values, ok := configFile[cacheImageConfigKey]; ok {
var images []string
for key := range values.(map[string]interface{}) {
images = append(images, key)

View File

@ -22,10 +22,11 @@ import (
"github.com/spf13/cobra"
cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
)
const defaultCacheListFormat = "{{.CacheImage}}\n"
var cacheListFormat string
// CacheListTemplate represents the cache list template
@ -39,7 +40,7 @@ var listCacheCmd = &cobra.Command{
Short: "List all available images from the local cache.",
Long: "List all available images from the local cache.",
Run: func(cmd *cobra.Command, args []string) {
images, err := cmdConfig.ListConfigMap(constants.Cache)
images, err := cmdConfig.ListConfigMap(cacheImageConfigKey)
if err != nil {
exit.WithError("Failed to get image map", err)
}
@ -50,7 +51,7 @@ var listCacheCmd = &cobra.Command{
}
func init() {
listCacheCmd.Flags().StringVar(&cacheListFormat, "format", constants.DefaultCacheListFormat,
listCacheCmd.Flags().StringVar(&cacheListFormat, "format", defaultCacheListFormat,
`Go template format string for the cache list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd#CacheListTemplate`)
cacheCmd.AddCommand(listCacheCmd)

View File

@ -25,7 +25,7 @@ import (
var AddonsCmd = &cobra.Command{
Use: "addons SUBCOMMAND [flags]",
Short: "Modify minikube's kubernetes addons",
Long: `addons modifies minikube addons files using subcommands like "minikube addons enable heapster"`,
Long: `addons modifies minikube addons files using subcommands like "minikube addons enable dashboard"`,
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
glog.Errorf("help: %v", err)

View File

@ -17,17 +17,23 @@ limitations under the License.
package config
import (
"encoding/json"
"fmt"
"os"
"sort"
"strings"
"text/template"
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/out"
)
const defaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n"
var addonListFormat string
var addonListOutput string
// AddonListTemplate represents the addon list template
type AddonListTemplate struct {
@ -43,28 +49,49 @@ var addonsListCmd = &cobra.Command{
if len(args) != 0 {
exit.UsageT("usage: minikube addons list")
}
err := addonList()
if err != nil {
exit.WithError("addon list failed", err)
if addonListOutput != "list" && addonListFormat != defaultAddonListFormat {
exit.UsageT("Cannot use both --output and --format options")
}
switch strings.ToLower(addonListOutput) {
case "list":
printAddonsList()
case "json":
printAddonsJSON()
default:
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'list', 'json'", addonListOutput))
}
},
}
func init() {
AddonsCmd.Flags().StringVar(&addonListFormat, "format", constants.DefaultAddonListFormat,
addonsListCmd.Flags().StringVarP(
&addonListFormat,
"format",
"f",
defaultAddonListFormat,
`Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`)
addonsListCmd.Flags().StringVarP(
&addonListOutput,
"output",
"o",
"list",
`minikube addons list --output OUTPUT. json, list`)
AddonsCmd.AddCommand(addonsListCmd)
}
func stringFromStatus(addonStatus bool) string {
var stringFromStatus = func(addonStatus bool) string {
if addonStatus {
return "enabled"
}
return "disabled"
}
func addonList() error {
var printAddonsList = func() {
addonNames := make([]string, 0, len(assets.Addons))
for addonName := range assets.Addons {
addonNames = append(addonNames, addonName)
@ -75,7 +102,7 @@ func addonList() error {
addonBundle := assets.Addons[addonName]
addonStatus, err := addonBundle.IsEnabled()
if err != nil {
return err
exit.WithError("Error getting addons status", err)
}
tmpl, err := template.New("list").Parse(addonListFormat)
if err != nil {
@ -87,5 +114,30 @@ func addonList() error {
exit.WithError("Error executing list template", err)
}
}
return nil
}
var printAddonsJSON = func() {
addonNames := make([]string, 0, len(assets.Addons))
for addonName := range assets.Addons {
addonNames = append(addonNames, addonName)
}
sort.Strings(addonNames)
addonsMap := map[string]map[string]interface{}{}
for _, addonName := range addonNames {
addonBundle := assets.Addons[addonName]
addonStatus, err := addonBundle.IsEnabled()
if err != nil {
exit.WithError("Error getting addons status", err)
}
addonsMap[addonName] = map[string]interface{}{
"Status": stringFromStatus(addonStatus),
}
}
jsonString, _ := json.Marshal(addonsMap)
out.String(string(jsonString))
}

View File

@ -22,7 +22,7 @@ import (
"github.com/golang/glog"
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/localpath"
)
// Bootstrapper is the name for bootstrapper
@ -159,12 +159,6 @@ var settings = []Setting{
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableStorageClasses},
},
{
name: "heapster",
set: SetBool,
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "efk",
set: SetBool,
@ -201,12 +195,6 @@ var settings = []Setting{
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "default-storageclass",
set: SetBool,
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableStorageClasses},
},
{
name: "storage-provisioner",
set: SetBool,
@ -248,6 +236,18 @@ var settings = []Setting{
validations: []setFn{IsValidAddon, IsContainerdRuntime},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "helm-tiller",
set: SetBool,
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "ingress-dns",
set: SetBool,
validations: []setFn{IsValidAddon},
callbacks: []setFn{EnableOrDisableAddon},
},
{
name: "hyperv-virtual-switch",
set: SetString,
@ -294,7 +294,7 @@ func configurableFields() string {
// ListConfigMap list entries from config file
func ListConfigMap(name string) ([]string, error) {
configFile, err := config.ReadConfig(constants.ConfigFile)
configFile, err := config.ReadConfig(localpath.ConfigFile)
if err != nil {
return nil, err
}
@ -314,7 +314,7 @@ func AddToConfigMap(name string, images []string) error {
return err
}
// Set the values
cfg, err := config.ReadConfig(constants.ConfigFile)
cfg, err := config.ReadConfig(localpath.ConfigFile)
if err != nil {
return err
}
@ -331,7 +331,7 @@ func AddToConfigMap(name string, images []string) error {
return err
}
// Write the values
return config.WriteConfig(constants.ConfigFile, cfg)
return config.WriteConfig(localpath.ConfigFile, cfg)
}
// DeleteFromConfigMap deletes entries from a map in the config file
@ -341,7 +341,7 @@ func DeleteFromConfigMap(name string, images []string) error {
return err
}
// Set the values
cfg, err := config.ReadConfig(constants.ConfigFile)
cfg, err := config.ReadConfig(localpath.ConfigFile)
if err != nil {
return err
}
@ -356,5 +356,5 @@ func DeleteFromConfigMap(name string, images []string) error {
return err
}
// Write the values
return config.WriteConfig(constants.ConfigFile, cfg)
return config.WriteConfig(localpath.ConfigFile, cfg)
}

View File

@ -16,10 +16,24 @@ limitations under the License.
package config
import "testing"
import (
"testing"
"gotest.tools/assert"
pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/localpath"
)
func TestDisableUnknownAddon(t *testing.T) {
if err := Set("InvalidAddon", "false"); err == nil {
t.Fatalf("Disable did not return error for unknown addon")
}
}
func TestDisableAddon(t *testing.T) {
if err := Set("dashboard", "false"); err != nil {
t.Fatalf("Disable returned unexpected error: " + err.Error())
}
config, _ := pkgConfig.ReadConfig(localpath.ConfigFile)
assert.Equal(t, config["dashboard"], false)
}

View File

@ -16,10 +16,24 @@ limitations under the License.
package config
import "testing"
import (
"testing"
"gotest.tools/assert"
pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/localpath"
)
func TestEnableUnknownAddon(t *testing.T) {
if err := Set("InvalidAddon", "false"); err == nil {
t.Fatalf("Enable did not return error for unknown addon")
}
}
func TestEnableAddon(t *testing.T) {
if err := Set("ingress", "true"); err != nil {
t.Fatalf("Enable returned unexpected error: " + err.Error())
}
config, _ := pkgConfig.ReadConfig(localpath.ConfigFile)
assert.Equal(t, config["ingress"], true)
}

View File

@ -17,12 +17,15 @@ limitations under the License.
package config
import (
"fmt"
"os"
"text/template"
"github.com/pkg/browser"
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
@ -63,7 +66,9 @@ var addonsOpenCmd = &cobra.Command{
}
defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 1)
if !cluster.IsMinikubeRunning(api) {
os.Exit(1)
}
addon, ok := assets.Addons[addonName] // validate addon input
if !ok {
exit.WithCodeT(exit.Data, `addon '{{.name}}' is not a valid addon packaged with minikube.
@ -93,9 +98,20 @@ You can add one by annotating a service with the label {{.labelName}}:{{.addonNa
}
for i := range serviceList.Items {
svc := serviceList.Items[i].ObjectMeta.Name
if err := service.WaitAndMaybeOpenService(api, namespace, svc, addonsURLTemplate, addonsURLMode, https, wait, interval); err != nil {
var urlString []string
if urlString, err = service.WaitForService(api, namespace, svc, addonsURLTemplate, addonsURLMode, https, wait, interval); err != nil {
exit.WithCodeT(exit.Unavailable, "Wait failed: {{.error}}", out.V{"error": err})
}
if len(urlString) != 0 {
out.T(out.Celebrate, "Opening kubernetes service {{.namespace_name}}/{{.service_name}} in default browser...", out.V{"namespace_name": namespace, "service_name": svc})
for _, url := range urlString {
if err := browser.OpenURL(url); err != nil {
exit.WithError(fmt.Sprintf("browser failed to open url %s", url), err)
}
}
}
}
},
}
@ -103,8 +119,8 @@ You can add one by annotating a service with the label {{.labelName}}:{{.addonNa
func init() {
addonsOpenCmd.Flags().BoolVar(&addonsURLMode, "url", false, "Display the kubernetes addons URL in the CLI instead of opening it in the default browser")
addonsOpenCmd.Flags().BoolVar(&https, "https", false, "Open the addons URL with https instead of http")
addonsOpenCmd.Flags().IntVar(&wait, "wait", constants.DefaultWait, "Amount of time to wait for service in seconds")
addonsOpenCmd.Flags().IntVar(&interval, "interval", constants.DefaultInterval, "The time interval for each check that wait performs in seconds")
addonsOpenCmd.Flags().IntVar(&wait, "wait", service.DefaultWait, "Amount of time to wait for service in seconds")
addonsOpenCmd.Flags().IntVar(&interval, "interval", service.DefaultInterval, "The time interval for each check that wait performs in seconds")
addonsOpenCmd.PersistentFlags().StringVar(&addonsURLFormat, "format", defaultAddonsFormatTemplate, "Format to output addons URL in. This format will be applied to each url individually and they will be printed one at a time.")
AddonsCmd.AddCommand(addonsOpenCmd)
}

View File

@ -45,8 +45,23 @@ var ProfileCmd = &cobra.Command{
}
profile := args[0]
/**
we need to add code over here to check whether the profile
name is in the list of reserved keywords
*/
if pkgConfig.ProfileNameInReservedKeywords(profile) {
out.ErrT(out.FailureType, `Profile name "{{.profilename}}" is minikube keyword. To delete profile use command minikube delete -p <profile name> `, out.V{"profilename": profile})
os.Exit(0)
}
if profile == "default" {
profile = "minikube"
} else {
// not validating when it is default profile
errProfile, ok := ValidateProfile(profile)
if !ok && errProfile != nil {
out.FailureT(errProfile.Msg)
}
}
if !pkgConfig.ProfileExists(profile) {
@ -71,7 +86,7 @@ var ProfileCmd = &cobra.Command{
out.SuccessT("Skipped switching kubectl context for {{.profile_name}} because --keep-context was set.", out.V{"profile_name": profile})
out.SuccessT("To connect to this cluster, use: kubectl --context={{.profile_name}}", out.V{"profile_name": profile})
} else {
err := kubeconfig.SetCurrentContext(constants.KubeconfigPath, profile)
err := kubeconfig.SetCurrentContext(profile, constants.KubeconfigPath)
if err != nil {
out.ErrT(out.Sad, `Error while setting kubectl current context : {{.error}}`, out.V{"error": err})
}

View File

@ -17,9 +17,11 @@ limitations under the License.
package config
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/exit"
@ -29,48 +31,101 @@ import (
"github.com/spf13/cobra"
)
var (
output string
)
var profileListCmd = &cobra.Command{
Use: "list",
Short: "Lists all minikube profiles.",
Long: "Lists all valid minikube profiles and detects all possible invalid profiles.",
Run: func(cmd *cobra.Command, args []string) {
var validData [][]string
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version"})
table.SetAutoFormatHeaders(false)
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
table.SetCenterSeparator("|")
validProfiles, invalidProfiles, err := config.ListProfiles()
if len(validProfiles) == 0 || err != nil {
exit.UsageT("No minikube profile was found. You can create one using `minikube start`.")
}
for _, p := range validProfiles {
validData = append(validData, []string{p.Name, p.Config.MachineConfig.VMDriver, p.Config.KubernetesConfig.NodeIP, strconv.Itoa(p.Config.KubernetesConfig.NodePort), p.Config.KubernetesConfig.KubernetesVersion})
switch strings.ToLower(output) {
case "json":
printProfilesJSON()
case "table":
printProfilesTable()
default:
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", output))
}
table.AppendBulk(validData)
table.Render()
if invalidProfiles != nil {
out.T(out.WarningType, "Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)})
for _, p := range invalidProfiles {
out.T(out.Empty, "\t "+p.Name)
}
out.T(out.Tip, "You can delete them using the following command(s): ")
for _, p := range invalidProfiles {
out.String(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name))
}
}
if err != nil {
exit.WithCodeT(exit.Config, fmt.Sprintf("error loading profiles: %v", err))
}
},
}
var printProfilesTable = func() {
var validData [][]string
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version"})
table.SetAutoFormatHeaders(false)
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
table.SetCenterSeparator("|")
validProfiles, invalidProfiles, err := config.ListProfiles()
if len(validProfiles) == 0 || err != nil {
exit.UsageT("No minikube profile was found. You can create one using `minikube start`.")
}
for _, p := range validProfiles {
validData = append(validData, []string{p.Name, p.Config.MachineConfig.VMDriver, p.Config.KubernetesConfig.NodeIP, strconv.Itoa(p.Config.KubernetesConfig.NodePort), p.Config.KubernetesConfig.KubernetesVersion})
}
table.AppendBulk(validData)
table.Render()
if invalidProfiles != nil {
out.T(out.WarningType, "Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)})
for _, p := range invalidProfiles {
out.T(out.Empty, "\t "+p.Name)
}
out.T(out.Tip, "You can delete them using the following command(s): ")
for _, p := range invalidProfiles {
out.String(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name))
}
}
if err != nil {
exit.WithCodeT(exit.Config, fmt.Sprintf("error loading profiles: %v", err))
}
}
var printProfilesJSON = func() {
validProfiles, invalidProfiles, err := config.ListProfiles()
var valid []*config.Profile
var invalid []*config.Profile
if validProfiles != nil {
valid = validProfiles
} else {
valid = []*config.Profile{}
}
if invalidProfiles != nil {
invalid = invalidProfiles
} else {
invalid = []*config.Profile{}
}
var body = map[string]interface{}{}
if err == nil {
body["valid"] = valid
body["invalid"] = invalid
jsonString, _ := json.Marshal(body)
out.String(string(jsonString))
} else {
body["error"] = err
jsonString, _ := json.Marshal(body)
out.String(string(jsonString))
os.Exit(exit.Failure)
}
}
func init() {
profileListCmd.Flags().StringVarP(&output, "output", "o", "table", "The output format. One of 'json', 'table'")
ProfileCmd.AddCommand(profileListCmd)
}

View File

@ -149,7 +149,7 @@ func posString(slice []string, element string) int {
return -1
}
// containsString returns true iff slice contains element
// containsString returns true if slice contains element
func containsString(slice []string, element string) bool {
return !(posString(slice, element) == -1)
return posString(slice, element) != -1
}

View File

@ -19,8 +19,8 @@ package config
import (
"github.com/spf13/cobra"
pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/out"
)
@ -60,7 +60,7 @@ func Set(name string, value string) error {
}
// Set the value
config, err := pkgConfig.ReadConfig(constants.ConfigFile)
config, err := pkgConfig.ReadConfig(localpath.ConfigFile)
if err != nil {
return err
}
@ -76,5 +76,5 @@ func Set(name string, value string) error {
}
// Write the value
return pkgConfig.WriteConfig(constants.ConfigFile, config)
return pkgConfig.WriteConfig(localpath.ConfigFile, config)
}

View File

@ -19,7 +19,7 @@ package config
import "testing"
func TestNotFound(t *testing.T) {
err := Set("nonexistant", "10")
err := Set("nonexistent", "10")
if err == nil {
t.Fatalf("Set did not return error for unknown property")
}

View File

@ -19,8 +19,8 @@ package config
import (
"github.com/spf13/cobra"
pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/localpath"
)
var configUnsetCmd = &cobra.Command{
@ -44,10 +44,10 @@ func init() {
// Unset unsets a property
func Unset(name string) error {
m, err := pkgConfig.ReadConfig(constants.ConfigFile)
m, err := pkgConfig.ReadConfig(localpath.ConfigFile)
if err != nil {
return err
}
delete(m, name)
return pkgConfig.WriteConfig(constants.ConfigFile, m)
return pkgConfig.WriteConfig(localpath.ConfigFile, m)
}

View File

@ -27,13 +27,15 @@ import (
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/command"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/storageclass"
)
// defaultStorageClassProvisioner is the name of the default storage class provisioner
const defaultStorageClassProvisioner = "standard"
// Runs all the validation or callback functions and collects errors
func run(name string, value string, fns []setFn) error {
var errors []error
@ -109,6 +111,18 @@ func EnableOrDisableAddon(name string, val string) error {
if err != nil {
return errors.Wrapf(err, "parsing bool: %s", name)
}
addon := assets.Addons[name]
// check addon status before enabling/disabling it
alreadySet, err := isAddonAlreadySet(addon, enable)
if err != nil {
out.ErrT(out.Conflict, "{{.error}}", out.V{"error": err})
return err
}
//if addon is already enabled or disabled, do nothing
if alreadySet {
return nil
}
// TODO(r2d4): config package should not reference API, pull this out
api, err := machine.NewAPIClient()
@ -116,13 +130,18 @@ func EnableOrDisableAddon(name string, val string) error {
return errors.Wrap(err, "machine client")
}
defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 0)
addon := assets.Addons[name]
//if minikube is not running, we return and simply update the value in the addon
//config and rewrite the file
if !cluster.IsMinikubeRunning(api) {
return nil
}
host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName())
if err != nil {
return errors.Wrap(err, "getting host")
}
cmd, err := machine.CommandRunner(host)
if err != nil {
return errors.Wrap(err, "command runner")
@ -137,30 +156,24 @@ func EnableOrDisableAddon(name string, val string) error {
return enableOrDisableAddonInternal(addon, cmd, data, enable)
}
func isAddonAlreadySet(addon *assets.Addon, enable bool) error {
func isAddonAlreadySet(addon *assets.Addon, enable bool) (bool, error) {
addonStatus, err := addon.IsEnabled()
if err != nil {
return errors.Wrap(err, "get the addon status")
return false, errors.Wrap(err, "get the addon status")
}
if addonStatus && enable {
return fmt.Errorf("addon %s was already enabled", addon.Name())
return true, nil
} else if !addonStatus && !enable {
return fmt.Errorf("addon %s was already disabled", addon.Name())
return true, nil
}
return nil
return false, nil
}
func enableOrDisableAddonInternal(addon *assets.Addon, cmd command.Runner, data interface{}, enable bool) error {
var err error
// check addon status before enabling/disabling it
if err := isAddonAlreadySet(addon, enable); err != nil {
out.ErrT(out.Conflict, "{{.error}}", out.V{"error": err})
os.Exit(0)
}
if enable {
for _, addon := range addon.Assets {
@ -205,7 +218,7 @@ func EnableOrDisableStorageClasses(name, val string) error {
return errors.Wrap(err, "Error parsing boolean")
}
class := constants.DefaultStorageClassProvisioner
class := defaultStorageClassProvisioner
if name == "storage-provisioner-gluster" {
class = "glusterfile"
}
@ -230,3 +243,42 @@ func EnableOrDisableStorageClasses(name, val string) error {
return EnableOrDisableAddon(name, val)
}
// ErrValidateProfile Error to validate profile
type ErrValidateProfile struct {
Name string
Msg string
}
func (e ErrValidateProfile) Error() string {
return e.Msg
}
// ValidateProfile checks if the profile user is trying to switch exists, else throws error
func ValidateProfile(profile string) (*ErrValidateProfile, bool) {
validProfiles, invalidProfiles, err := config.ListProfiles()
if err != nil {
out.FailureT(err.Error())
}
// handling invalid profiles
for _, invalidProf := range invalidProfiles {
if profile == invalidProf.Name {
return &ErrValidateProfile{Name: profile, Msg: fmt.Sprintf("%q is an invalid profile", profile)}, false
}
}
profileFound := false
// valid profiles if found, setting profileFound to trueexpectedMsg
for _, prof := range validProfiles {
if prof.Name == profile {
profileFound = true
break
}
}
if !profileFound {
return &ErrValidateProfile{Name: profile, Msg: fmt.Sprintf("profile %q not found", profile)}, false
}
return nil, true
}

View File

@ -17,21 +17,22 @@ limitations under the License.
package config
import (
"fmt"
"testing"
"k8s.io/minikube/pkg/minikube/assets"
pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
)
var minikubeConfig = pkgConfig.MinikubeConfig{
"vm-driver": constants.DriverKvm2,
"vm-driver": driver.KVM2,
"cpus": 12,
"show-libmachine-logs": true,
}
func TestFindSettingNotFound(t *testing.T) {
s, err := findSetting("nonexistant")
s, err := findSetting("nonexistent")
if err == nil {
t.Fatalf("Shouldn't have found setting, but did. [%+v]", s)
}
@ -48,9 +49,9 @@ func TestFindSetting(t *testing.T) {
}
func TestSetString(t *testing.T) {
err := SetString(minikubeConfig, "vm-driver", constants.DriverVirtualbox)
err := SetString(minikubeConfig, "vm-driver", driver.VirtualBox)
if err != nil {
t.Fatalf("Couldnt set string: %v", err)
t.Fatalf("Couldn't set string: %v", err)
}
}
@ -85,15 +86,13 @@ func TestSetBool(t *testing.T) {
func TestIsAddonAlreadySet(t *testing.T) {
testCases := []struct {
addonName string
expectErr string
}{
{
addonName: "ingress",
expectErr: "addon ingress was already ",
},
{
addonName: "heapster",
expectErr: "addon heapster was already ",
addonName: "registry",
},
}
@ -101,13 +100,39 @@ func TestIsAddonAlreadySet(t *testing.T) {
addon := assets.Addons[test.addonName]
addonStatus, _ := addon.IsEnabled()
expectMsg := test.expectErr + "enabled"
if !addonStatus {
expectMsg = test.expectErr + "disabled"
alreadySet, err := isAddonAlreadySet(addon, addonStatus)
if !alreadySet {
if addonStatus {
t.Errorf("Did not get expected status, \n\n expected %+v already enabled", test.addonName)
} else {
t.Errorf("Did not get expected status, \n\n expected %+v already disabled", test.addonName)
}
}
err := isAddonAlreadySet(addon, addonStatus)
if err.Error() != expectMsg {
t.Errorf("Did not get expected error, \n\n expected: %+v \n\n actual: %+v", expectMsg, err)
if err != nil {
t.Errorf("Got unexpected error: %+v", err)
}
}
}
func TestValidateProfile(t *testing.T) {
testCases := []struct {
profileName string
}{
{
profileName: "82374328742_2974224498",
},
{
profileName: "minikube",
},
}
for _, test := range testCases {
profileNam := test.profileName
expectedMsg := fmt.Sprintf("profile %q not found", test.profileName)
err, ok := ValidateProfile(profileNam)
if !ok && err.Error() != expectedMsg {
t.Errorf("Didnt receive expected message")
}
}
}

View File

@ -28,8 +28,8 @@ import (
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/cruntime"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/out"
)
@ -44,13 +44,11 @@ and then start minikube again with the following flags:
minikube start --container-runtime=containerd --docker-opt containerd=/var/run/containerd/containerd.sock`
// IsValidDriver checks if a driver is supported
func IsValidDriver(string, driver string) error {
for _, d := range constants.SupportedVMDrivers {
if driver == d {
return nil
}
func IsValidDriver(string, name string) error {
if driver.Supported(name) {
return nil
}
return fmt.Errorf("driver %q is not supported", driver)
return fmt.Errorf("driver %q is not supported", name)
}
// RequiresRestartMsg returns the "requires restart" message

View File

@ -22,10 +22,12 @@ import (
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/localpath"
)
const defaultConfigViewFormat = "- {{.ConfigKey}}: {{.ConfigValue}}\n"
var viewFormat string
// ViewTemplate represents the view template
@ -47,7 +49,7 @@ var configViewCmd = &cobra.Command{
}
func init() {
configViewCmd.Flags().StringVar(&viewFormat, "format", constants.DefaultConfigViewFormat,
configViewCmd.Flags().StringVar(&viewFormat, "format", defaultConfigViewFormat,
`Go template format string for the config view output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#ConfigViewTemplate`)
ConfigCmd.AddCommand(configViewCmd)
@ -55,7 +57,7 @@ For the list of accessible variables for the template, see the struct values her
// View displays the current config
func View() error {
cfg, err := config.ReadConfig(constants.ConfigFile)
cfg, err := config.ReadConfig(localpath.ConfigFile)
if err != nil {
return err
}

View File

@ -93,7 +93,9 @@ var dashboardCmd = &cobra.Command{
exit.WithCodeT(exit.NoInput, "kubectl not found in PATH, but is required for the dashboard. Installation guide: https://kubernetes.io/docs/tasks/tools/install-kubectl/")
}
cluster.EnsureMinikubeRunningOrExit(api, 1)
if !cluster.IsMinikubeRunning(api) {
os.Exit(1)
}
// Check dashboard status before enabling it
dashboardAddon := assets.Addons["dashboard"]

View File

@ -23,17 +23,19 @@ import (
"path/filepath"
"strconv"
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/mcnerror"
"github.com/golang/glog"
ps "github.com/mitchellh/go-ps"
"github.com/mitchellh/go-ps"
"github.com/pkg/errors"
"github.com/docker/machine/libmachine"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/cluster"
pkg_config "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/kubeconfig"
"k8s.io/minikube/pkg/minikube/localpath"
@ -41,6 +43,9 @@ import (
"k8s.io/minikube/pkg/minikube/out"
)
var deleteAll bool
var purge bool
// deleteCmd represents the delete command
var deleteCmd = &cobra.Command{
Use: "delete",
@ -50,26 +55,156 @@ associated files.`,
Run: runDelete,
}
type typeOfError int
const (
// Fatal is a type of DeletionError
Fatal typeOfError = 0
// MissingProfile is a type of DeletionError
MissingProfile typeOfError = 1
// MissingCluster is a type of DeletionError
MissingCluster typeOfError = 2
)
// DeletionError can be returned from DeleteProfiles
type DeletionError struct {
Err error
Errtype typeOfError
}
func (error DeletionError) Error() string {
return error.Err.Error()
}
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.")
if err := viper.BindPFlags(deleteCmd.Flags()); err != nil {
exit.WithError("unable to bind flags", err)
}
RootCmd.AddCommand(deleteCmd)
}
// runDelete handles the executes the flow of "minikube delete"
func runDelete(cmd *cobra.Command, args []string) {
if len(args) > 0 {
exit.UsageT("Usage: minikube delete")
}
profile := viper.GetString(pkg_config.MachineProfile)
profileFlag, err := cmd.Flags().GetString("profile")
if err != nil {
exit.WithError("Could not get profile flag", err)
}
validProfiles, invalidProfiles, err := pkg_config.ListProfiles()
profilesToDelete := append(validProfiles, invalidProfiles...)
// If the purge flag is set, go ahead and delete the .minikube directory.
if purge && len(profilesToDelete) > 1 && !deleteAll {
out.ErrT(out.Notice, "Multiple minikube profiles were found - ")
for _, p := range profilesToDelete {
out.T(out.Notice, " - {{.profile}}", out.V{"profile": p.Name})
}
exit.UsageT("Usage: minikube delete --all --purge")
}
if deleteAll {
if profileFlag != constants.DefaultMachineName {
exit.UsageT("usage: minikube delete --all")
}
if err != nil {
exit.WithError("Error getting profiles to delete", err)
}
errs := DeleteProfiles(profilesToDelete)
if len(errs) > 0 {
HandleDeletionErrors(errs)
} else {
out.T(out.DeletingHost, "Successfully deleted all profiles")
}
} else {
if len(args) > 0 {
exit.UsageT("usage: minikube delete")
}
profileName := viper.GetString(pkg_config.MachineProfile)
profile, err := pkg_config.LoadProfile(profileName)
if err != nil {
out.ErrT(out.Meh, `"{{.name}}" profile does not exist`, out.V{"name": profileName})
}
errs := DeleteProfiles([]*pkg_config.Profile{profile})
if len(errs) > 0 {
HandleDeletionErrors(errs)
} else {
out.T(out.DeletingHost, "Successfully deleted profile \"{{.name}}\"", out.V{"name": profileName})
}
}
// If the purge flag is set, go ahead and delete the .minikube directory.
if purge {
purgeMinikubeDirectory()
}
}
func purgeMinikubeDirectory() {
glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath())
if err := os.RemoveAll(localpath.MiniPath()); err != nil {
exit.WithError("unable to delete minikube config folder", err)
}
out.T(out.Crushed, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory": localpath.MiniPath()})
}
// DeleteProfiles deletes one or more profiles
func DeleteProfiles(profiles []*pkg_config.Profile) []error {
var errs []error
for _, profile := range profiles {
err := deleteProfile(profile)
if err != nil {
mm, loadErr := cluster.LoadMachine(profile.Name)
if !profile.IsValid() || (loadErr != nil || !mm.IsValid()) {
invalidProfileDeletionErrs := deleteInvalidProfile(profile)
if len(invalidProfileDeletionErrs) > 0 {
errs = append(errs, invalidProfileDeletionErrs...)
}
} else {
errs = append(errs, err)
}
}
}
return errs
}
func deleteProfile(profile *pkg_config.Profile) error {
viper.Set(pkg_config.MachineProfile, profile.Name)
api, err := machine.NewAPIClient()
if err != nil {
exit.WithError("Error getting client", err)
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("error getting client %v", err))
return DeletionError{Err: delErr, Errtype: Fatal}
}
defer api.Close()
cc, err := pkg_config.Load()
if err != nil && !os.IsNotExist(err) {
out.ErrT(out.Sad, "Error loading profile {{.name}}: {{.error}}", out.V{"name": profile, "error": err})
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("error loading profile config: %v", err))
return DeletionError{Err: delErr, Errtype: MissingProfile}
}
// In the case of "none", we want to uninstall Kubernetes as there is no VM to delete
if err == nil && cc.MachineConfig.VMDriver == constants.DriverNone {
uninstallKubernetes(api, cc.KubernetesConfig, viper.GetString(cmdcfg.Bootstrapper))
if err == nil && driver.BareMetal(cc.MachineConfig.VMDriver) {
if err := uninstallKubernetes(api, cc.KubernetesConfig, viper.GetString(cmdcfg.Bootstrapper)); err != nil {
deletionError, ok := err.(DeletionError)
if ok {
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("%v", err))
deletionError.Err = delErr
return deletionError
}
return err
}
}
if err := killMountProcess(); err != nil {
@ -79,14 +214,125 @@ func runDelete(cmd *cobra.Command, args []string) {
if err = cluster.DeleteHost(api); err != nil {
switch errors.Cause(err).(type) {
case mcnerror.ErrHostDoesNotExist:
out.T(out.Meh, `"{{.name}}" cluster does not exist`, out.V{"name": profile})
out.T(out.Meh, `"{{.name}}" cluster does not exist. Proceeding ahead with cleanup.`, out.V{"name": profile.Name})
default:
out.T(out.FailureType, "Failed to delete cluster: {{.error}}", out.V{"error": err})
out.T(out.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, out.V{"name": profile})
out.T(out.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, out.V{"name": profile.Name})
}
}
// In case DeleteHost didn't complete the job.
deleteProfileDirectory(profile.Name)
if err := pkg_config.DeleteProfile(profile.Name); err != nil {
if os.IsNotExist(err) {
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("\"%s\" profile does not exist", profile.Name))
return DeletionError{Err: delErr, Errtype: MissingProfile}
}
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("failed to remove profile %v", err))
return DeletionError{Err: delErr, Errtype: Fatal}
}
out.T(out.Crushed, `The "{{.name}}" cluster has been deleted.`, out.V{"name": profile.Name})
machineName := pkg_config.GetMachineName()
if err := deleteContext(machineName); err != nil {
return err
}
return nil
}
func deleteContext(machineName string) error {
if err := kubeconfig.DeleteContext(constants.KubeconfigPath, machineName); err != nil {
return DeletionError{Err: fmt.Errorf("update config: %v", err), Errtype: Fatal}
}
if err := cmdcfg.Unset(pkg_config.MachineProfile); err != nil {
return DeletionError{Err: fmt.Errorf("unset minikube profile: %v", err), Errtype: Fatal}
}
return nil
}
func deleteInvalidProfile(profile *pkg_config.Profile) []error {
out.T(out.DeletingHost, "Trying to delete invalid profile {{.profile}}", out.V{"profile": profile.Name})
var errs []error
pathToProfile := pkg_config.ProfileFolderPath(profile.Name, localpath.MiniPath())
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
err := os.RemoveAll(pathToProfile)
if err != nil {
errs = append(errs, DeletionError{err, Fatal})
}
}
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
err := os.RemoveAll(pathToMachine)
if err != nil {
errs = append(errs, DeletionError{err, Fatal})
}
}
return errs
}
func profileDeletionErr(profileName string, additionalInfo string) error {
return fmt.Errorf("error deleting profile \"%s\": %s", profileName, additionalInfo)
}
func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsName string) error {
out.T(out.Resetting, "Uninstalling Kubernetes {{.kubernetes_version}} using {{.bootstrapper_name}} ...", out.V{"kubernetes_version": kc.KubernetesVersion, "bootstrapper_name": bsName})
clusterBootstrapper, err := getClusterBootstrapper(api, bsName)
if err != nil {
return DeletionError{Err: fmt.Errorf("unable to get bootstrapper: %v", err), Errtype: Fatal}
} else if err = clusterBootstrapper.DeleteCluster(kc); err != nil {
return DeletionError{Err: fmt.Errorf("failed to delete cluster: %v", err), Errtype: Fatal}
}
return nil
}
// HandleDeletionErrors handles deletion errors from DeleteProfiles
func HandleDeletionErrors(errors []error) {
if len(errors) == 1 {
handleSingleDeletionError(errors[0])
} else {
handleMultipleDeletionErrors(errors)
}
}
func handleSingleDeletionError(err error) {
deletionError, ok := err.(DeletionError)
if ok {
switch deletionError.Errtype {
case Fatal:
out.FatalT(deletionError.Error())
case MissingProfile:
out.ErrT(out.Sad, deletionError.Error())
case MissingCluster:
out.ErrT(out.Meh, deletionError.Error())
default:
out.FatalT(deletionError.Error())
}
} else {
exit.WithError("Could not process error from failed deletion", err)
}
}
func handleMultipleDeletionErrors(errors []error) {
out.ErrT(out.Sad, "Multiple errors deleting profiles")
for _, err := range errors {
deletionError, ok := err.(DeletionError)
if ok {
glog.Errorln(deletionError.Error())
} else {
exit.WithError("Could not process errors from failed deletion", err)
}
}
}
func deleteProfileDirectory(profile string) {
machineDir := filepath.Join(localpath.MiniPath(), "machines", profile)
if _, err := os.Stat(machineDir); err == nil {
out.T(out.DeletingHost, `Removing {{.directory}} ...`, out.V{"directory": machineDir})
@ -95,34 +341,6 @@ func runDelete(cmd *cobra.Command, args []string) {
exit.WithError("Unable to remove machine directory: %v", err)
}
}
if err := pkg_config.DeleteProfile(profile); err != nil {
if os.IsNotExist(err) {
out.T(out.Meh, `"{{.name}}" profile does not exist`, out.V{"name": profile})
os.Exit(0)
}
exit.WithError("Failed to remove profile", err)
}
out.T(out.Crushed, `The "{{.name}}" cluster has been deleted.`, out.V{"name": profile})
machineName := pkg_config.GetMachineName()
if err := kubeconfig.DeleteContext(constants.KubeconfigPath, machineName); err != nil {
exit.WithError("update config", err)
}
if err := cmdcfg.Unset(pkg_config.MachineProfile); err != nil {
exit.WithError("unset minikube profile", err)
}
}
func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsName string) {
out.T(out.Resetting, "Uninstalling Kubernetes {{.kubernetes_version}} using {{.bootstrapper_name}} ...", out.V{"kubernetes_version": kc.KubernetesVersion, "bootstrapper_name": bsName})
clusterBootstrapper, err := getClusterBootstrapper(api, bsName)
if err != nil {
out.ErrT(out.Empty, "Unable to get bootstrapper: {{.error}}", out.V{"error": err})
} else if err = clusterBootstrapper.DeleteCluster(kc); err != nil {
out.ErrT(out.Empty, "Failed to delete cluster: {{.error}}", out.V{"error": err})
}
}
// killMountProcess kills the mount process, if it is running

View File

@ -0,0 +1,216 @@
/*
Copyright 2016 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 cmd
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/otiai10/copy"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/localpath"
)
// except returns a list of strings, minus the excluded ones
func exclude(vals []string, exclude []string) []string {
result := []string{}
for _, v := range vals {
excluded := false
for _, e := range exclude {
if e == v {
excluded = true
continue
}
}
if !excluded {
result = append(result, v)
}
}
return result
}
func fileNames(path string) ([]string, error) {
result := []string{}
fis, err := ioutil.ReadDir(path)
if err != nil {
return result, err
}
for _, fi := range fis {
result = append(result, fi.Name())
}
return result, nil
}
func TestDeleteProfile(t *testing.T) {
td, err := ioutil.TempDir("", "single")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
err = copy.Copy("../../../pkg/minikube/config/testdata/delete-single", td)
if err != nil {
t.Fatalf("copy: %v", err)
}
tests := []struct {
name string
profile string
expected []string
}{
{"normal", "p1", []string{"p1"}},
{"empty-profile", "p2_empty_profile_config", []string{"p2_empty_profile_config"}},
{"invalid-profile", "p3_invalid_profile_config", []string{"p3_invalid_profile_config"}},
{"partial-profile", "p4_partial_profile_config", []string{"p4_partial_profile_config"}},
{"missing-mach", "p5_missing_machine_config", []string{"p5_missing_machine_config"}},
{"empty-mach", "p6_empty_machine_config", []string{"p6_empty_machine_config"}},
{"invalid-mach", "p7_invalid_machine_config", []string{"p7_invalid_machine_config"}},
{"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err = os.Setenv(localpath.MinikubeHome, td)
if err != nil {
t.Errorf("setenv: %v", err)
}
beforeProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
if err != nil {
t.Errorf("readdir: %v", err)
}
beforeMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
if err != nil {
t.Errorf("readdir: %v", err)
}
profile, err := config.LoadProfile(tt.profile)
if err != nil {
t.Logf("load failure: %v", err)
}
errs := DeleteProfiles([]*config.Profile{profile})
if len(errs) > 0 {
HandleDeletionErrors(errs)
t.Errorf("Errors while deleting profiles: %v", errs)
}
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
}
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
}
afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
if err != nil {
t.Errorf("readdir profiles: %v", err)
}
afterMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
if err != nil {
t.Errorf("readdir machines: %v", err)
}
expectedProfiles := exclude(beforeProfiles, tt.expected)
if diff := cmp.Diff(expectedProfiles, afterProfiles); diff != "" {
t.Errorf("profiles mismatch (-want +got):\n%s", diff)
}
expectedMachines := exclude(beforeMachines, tt.expected)
if diff := cmp.Diff(expectedMachines, afterMachines); diff != "" {
t.Errorf("machines mismatch (-want +got):\n%s", diff)
}
viper.Set(config.MachineProfile, "")
})
}
}
func TestDeleteAllProfiles(t *testing.T) {
td, err := ioutil.TempDir("", "all")
if err != nil {
t.Fatalf("tempdir: %v", err)
}
err = copy.Copy("../../../pkg/minikube/config/testdata/delete-all", td)
if err != nil {
t.Fatalf("copy: %v", err)
}
err = os.Setenv(localpath.MinikubeHome, td)
if err != nil {
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
}
pFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
if err != nil {
t.Errorf("filenames: %v", err)
}
mFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
if err != nil {
t.Errorf("filenames: %v", err)
}
const numberOfTotalProfileDirs = 8
if numberOfTotalProfileDirs != len(pFiles) {
t.Errorf("got %d test profiles, expected %d: %s", len(pFiles), numberOfTotalProfileDirs, pFiles)
}
const numberOfTotalMachineDirs = 7
if numberOfTotalMachineDirs != len(mFiles) {
t.Errorf("got %d test machines, expected %d: %s", len(mFiles), numberOfTotalMachineDirs, mFiles)
}
validProfiles, inValidProfiles, err := config.ListProfiles()
if err != nil {
t.Error(err)
}
if numberOfTotalProfileDirs != len(validProfiles)+len(inValidProfiles) {
t.Errorf("ListProfiles length = %d, expected %d\nvalid: %v\ninvalid: %v\n", len(validProfiles)+len(inValidProfiles), numberOfTotalProfileDirs, validProfiles, inValidProfiles)
}
profiles := append(validProfiles, inValidProfiles...)
errs := DeleteProfiles(profiles)
if errs != nil {
t.Errorf("errors while deleting all profiles: %v", errs)
}
afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
if err != nil {
t.Errorf("profiles: %v", err)
}
afterMachines, err := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
if err != nil {
t.Errorf("machines: %v", err)
}
if len(afterProfiles) != 0 {
t.Errorf("Did not delete all profiles, remaining: %v", afterProfiles)
}
if len(afterMachines) != 0 {
t.Errorf("Did not delete all machines, remaining: %v", afterMachines)
}
viper.Set(config.MachineProfile, "")
}

View File

@ -35,7 +35,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
)
@ -343,7 +343,7 @@ var dockerEnvCmd = &cobra.Command{
if err != nil {
exit.WithError("Error getting host", err)
}
if host.Driver.DriverName() == constants.DriverNone {
if host.Driver.DriverName() == driver.None {
exit.UsageT(`'none' driver does not support 'minikube docker-env' command`)
}
hostSt, err := cluster.GetHostStatus(api)

View File

@ -31,15 +31,19 @@ import (
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/third_party/go9p/ufs"
)
// nineP is the value of --type used for the 9p filesystem.
const nineP = "9p"
const (
// nineP is the value of --type used for the 9p filesystem.
nineP = "9p"
defaultMountVersion = "9p2000.L"
defaultMsize = 262144
)
// placeholders for flag values
var mountIP string
@ -103,7 +107,7 @@ var mountCmd = &cobra.Command{
if err != nil {
exit.WithError("Error loading api", err)
}
if host.Driver.DriverName() == constants.DriverNone {
if host.Driver.DriverName() == driver.None {
exit.UsageT(`'none' driver does not support 'minikube mount' command`)
}
var ip net.IP
@ -202,13 +206,13 @@ var mountCmd = &cobra.Command{
func init() {
mountCmd.Flags().StringVar(&mountIP, "ip", "", "Specify the ip that the mount should be setup on")
mountCmd.Flags().StringVar(&mountType, "type", nineP, "Specify the mount filesystem type (supported types: 9p)")
mountCmd.Flags().StringVar(&mountVersion, "9p-version", constants.DefaultMountVersion, "Specify the 9p version that the mount should use")
mountCmd.Flags().StringVar(&mountVersion, "9p-version", defaultMountVersion, "Specify the 9p version that the mount should use")
mountCmd.Flags().BoolVar(&isKill, "kill", false, "Kill the mount process spawned by minikube start")
mountCmd.Flags().StringVar(&uid, "uid", "docker", "Default user id used for the mount")
mountCmd.Flags().StringVar(&gid, "gid", "docker", "Default group id used for the mount")
mountCmd.Flags().UintVar(&mode, "mode", 0755, "File permissions used for the mount")
mountCmd.Flags().StringSliceVar(&options, "options", []string{}, "Additional mount options, such as cache=fscache")
mountCmd.Flags().IntVar(&mSize, "msize", constants.DefaultMsize, "The number of bytes to use for 9p packet payload")
mountCmd.Flags().IntVar(&mSize, "msize", defaultMsize, "The number of bytes to use for 9p packet payload")
}
// getPort asks the kernel for a free open port that is ready to use

View File

@ -161,7 +161,7 @@ func setFlagsUsingViper() {
func init() {
translate.DetermineLocale()
RootCmd.PersistentFlags().StringP(config.MachineProfile, "p", constants.DefaultMachineName, `The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently.`)
RootCmd.PersistentFlags().StringP(configCmd.Bootstrapper, "b", constants.DefaultClusterBootstrapper, "The name of the cluster bootstrapper that will set up the kubernetes cluster.")
RootCmd.PersistentFlags().StringP(configCmd.Bootstrapper, "b", "kubeadm", "The name of the cluster bootstrapper that will set up the kubernetes cluster.")
groups := templates.CommandGroups{
{
@ -232,18 +232,20 @@ func init() {
// initConfig reads in config file and ENV variables if set.
func initConfig() {
configPath := constants.ConfigFile
configPath := localpath.ConfigFile
viper.SetConfigFile(configPath)
viper.SetConfigType("json")
err := viper.ReadInConfig()
if err != nil {
glog.Warningf("Error reading config file at %s: %v", configPath, err)
if err := viper.ReadInConfig(); err != nil {
// This config file is optional, so don't emit errors if missing
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
glog.Warningf("Error reading config file at %s: %v", configPath, err)
}
}
setupViper()
}
func setupViper() {
viper.SetEnvPrefix(constants.MinikubeEnvPrefix)
viper.SetEnvPrefix(minikubeEnvPrefix)
// Replaces '-' in flags with '_' in env variables
// e.g. iso-url => $ENVPREFIX_ISO_URL
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))

View File

@ -26,7 +26,6 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/tests"
)
@ -97,7 +96,7 @@ func runCommand(f func(*cobra.Command, []string)) {
func hideEnv(t *testing.T) func(t *testing.T) {
envs := make(map[string]string)
for _, env := range os.Environ() {
if strings.HasPrefix(env, constants.MinikubeEnvPrefix) {
if strings.HasPrefix(env, minikubeEnvPrefix) {
line := strings.Split(env, "=")
key, val := line[0], line[1]
envs[key] = val
@ -143,7 +142,7 @@ func TestViperConfig(t *testing.T) {
}
func getEnvVarName(name string) string {
return constants.MinikubeEnvPrefix + "_" + strings.ToUpper(name)
return minikubeEnvPrefix + "_" + strings.ToUpper(name)
}
func setValues(tt configTest) error {

View File

@ -17,13 +17,19 @@ limitations under the License.
package cmd
import (
"fmt"
"net/url"
"os"
"text/template"
"github.com/golang/glog"
"github.com/pkg/browser"
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/service"
)
@ -65,12 +71,32 @@ var serviceCmd = &cobra.Command{
}
defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 1)
err = service.WaitAndMaybeOpenService(api, namespace, svc,
serviceURLTemplate, serviceURLMode, https, wait, interval)
if !cluster.IsMinikubeRunning(api) {
os.Exit(1)
}
urls, err := service.WaitForService(api, namespace, svc, serviceURLTemplate, serviceURLMode, https, wait, interval)
if err != nil {
exit.WithError("Error opening service", err)
}
for _, u := range urls {
_, err := url.Parse(u)
if err != nil {
glog.Warningf("failed to parse url %q: %v (will not open)", u, err)
out.String(fmt.Sprintf("%s\n", u))
continue
}
if serviceURLMode {
out.String(fmt.Sprintf("%s\n", u))
continue
}
out.T(out.Celebrate, "Opening service {{.namespace_name}}/{{.service_name}} in default browser...", out.V{"namespace_name": namespace, "service_name": svc})
if err := browser.OpenURL(u); err != nil {
exit.WithError(fmt.Sprintf("open url failed: %s", u), err)
}
}
},
}
@ -78,8 +104,8 @@ func init() {
serviceCmd.Flags().StringVarP(&namespace, "namespace", "n", "default", "The service namespace")
serviceCmd.Flags().BoolVar(&serviceURLMode, "url", false, "Display the kubernetes service URL in the CLI instead of opening it in the default browser")
serviceCmd.Flags().BoolVar(&https, "https", false, "Open the service URL with https instead of http")
serviceCmd.Flags().IntVar(&wait, "wait", constants.DefaultWait, "Amount of time to wait for a service in seconds")
serviceCmd.Flags().IntVar(&interval, "interval", constants.DefaultInterval, "The initial time interval for each check that wait performs in seconds")
serviceCmd.Flags().IntVar(&wait, "wait", service.DefaultWait, "Amount of time to wait for a service in seconds")
serviceCmd.Flags().IntVar(&interval, "interval", service.DefaultInterval, "The initial time interval for each check that wait performs in seconds")
serviceCmd.PersistentFlags().StringVar(&serviceURLFormat, "format", defaultServiceFormatTemplate, "Format to output service URL in. This format will be applied to each url individually and they will be printed one at a time.")

View File

@ -25,7 +25,7 @@ import (
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/out"
@ -46,7 +46,7 @@ var sshCmd = &cobra.Command{
if err != nil {
exit.WithError("Error getting host", err)
}
if host.Driver.DriverName() == constants.DriverNone {
if host.Driver.DriverName() == driver.None {
exit.UsageT("'none' driver does not support 'minikube ssh' command")
}
if viper.GetBool(nativeSSH) {

View File

@ -17,7 +17,9 @@ limitations under the License.
package cmd
import (
"encoding/json"
"fmt"
"math"
"net"
"net/url"
"os"
@ -37,13 +39,13 @@ import (
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/pkg/errors"
"github.com/shirou/gopsutil/cpu"
gopshost "github.com/shirou/gopsutil/host"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/sync/errgroup"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/drivers"
"k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/bootstrapper/images"
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
@ -52,7 +54,7 @@ import (
cfg "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/cruntime"
"k8s.io/minikube/pkg/minikube/drivers/none"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/kubeconfig"
"k8s.io/minikube/pkg/minikube/localpath"
@ -61,6 +63,7 @@ import (
"k8s.io/minikube/pkg/minikube/notify"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/proxy"
"k8s.io/minikube/pkg/minikube/translate"
pkgutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/pkg/util/lock"
"k8s.io/minikube/pkg/util/retry"
@ -85,6 +88,9 @@ const (
kvmQemuURI = "kvm-qemu-uri"
kvmGPU = "kvm-gpu"
kvmHidden = "kvm-hidden"
minikubeEnvPrefix = "MINIKUBE"
defaultMemorySize = "2000mb"
defaultDiskSize = "20000mb"
keepContext = "keep-context"
createMount = "mount"
featureGates = "feature-gates"
@ -96,6 +102,7 @@ const (
imageMirrorCountry = "image-mirror-country"
mountString = "mount-string"
disableDriverMounts = "disable-driver-mounts"
addons = "addons"
cacheImages = "cache-images"
uuid = "uuid"
vpnkitSock = "hyperkit-vpnkit-sock"
@ -110,17 +117,21 @@ const (
interactive = "interactive"
waitTimeout = "wait-timeout"
nativeSSH = "native-ssh"
minimumMemorySize = "1024mb"
minimumCPUS = 2
minimumDiskSize = "2000mb"
autoUpdate = "auto-update-drivers"
)
var (
registryMirror []string
dockerEnv []string
dockerOpt []string
insecureRegistry []string
apiServerNames []string
apiServerIPs []net.IP
extraOptions cfg.ExtraOptionSlice
enableUpdateNotification = true
registryMirror []string
dockerEnv []string
dockerOpt []string
insecureRegistry []string
apiServerNames []string
addonList []string
apiServerIPs []net.IP
extraOptions cfg.ExtraOptionSlice
)
func init() {
@ -136,7 +147,7 @@ func init() {
// initMinikubeFlags includes commandline flags for minikube.
func initMinikubeFlags() {
viper.SetEnvPrefix(constants.MinikubeEnvPrefix)
viper.SetEnvPrefix(minikubeEnvPrefix)
// Replaces '-' in flags with '_' in env variables
// e.g. iso-url => $ENVPREFIX_ISO_URL
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
@ -145,23 +156,25 @@ func initMinikubeFlags() {
startCmd.Flags().Bool(force, false, "Force minikube to perform possibly dangerous operations")
startCmd.Flags().Bool(interactive, true, "Allow user prompts for more information")
startCmd.Flags().Int(cpus, constants.DefaultCPUS, "Number of CPUs allocated to the minikube VM.")
startCmd.Flags().String(memory, constants.DefaultMemorySize, "Amount of RAM allocated to the minikube VM (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().String(humanReadableDiskSize, constants.DefaultDiskSize, "Disk size allocated to the minikube VM (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().Int(cpus, 2, "Number of CPUs allocated to the minikube VM.")
startCmd.Flags().String(memory, defaultMemorySize, "Amount of RAM allocated to the minikube VM (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().String(humanReadableDiskSize, defaultDiskSize, "Disk size allocated to the minikube VM (format: <number>[<unit>], where unit = b, k, m or g).")
startCmd.Flags().Bool(downloadOnly, false, "If true, only download and cache files for later use - don't install or start anything.")
startCmd.Flags().Bool(cacheImages, true, "If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --vm-driver=none.")
startCmd.Flags().String(isoURL, constants.DefaultISOURL, "Location of the minikube iso.")
startCmd.Flags().Bool(keepContext, constants.DefaultKeepContext, "This will keep the existing kubectl context and will create a minikube context.")
startCmd.Flags().Bool(embedCerts, constants.DefaultEmbedCerts, "if true, will embed the certs in kubeconfig.")
startCmd.Flags().Bool(keepContext, false, "This will keep the existing kubectl context and will create a minikube context.")
startCmd.Flags().Bool(embedCerts, false, "if true, will embed the certs in kubeconfig.")
startCmd.Flags().String(containerRuntime, "docker", "The container runtime to be used (docker, crio, containerd).")
startCmd.Flags().Bool(createMount, false, "This will start the mount daemon and automatically mount files into minikube.")
startCmd.Flags().String(mountString, constants.DefaultMountDir+":"+constants.DefaultMountEndpoint, "The argument to pass the minikube mount command on start.")
startCmd.Flags().String(mountString, constants.DefaultMountDir+":/minikube-host", "The argument to pass the minikube mount command on start.")
startCmd.Flags().StringArrayVar(&addonList, addons, nil, "Enable addons. see `minikube addons list` for a list of valid addon names.")
startCmd.Flags().String(criSocket, "", "The cri socket path to be used.")
startCmd.Flags().String(networkPlugin, "", "The name of the network plugin.")
startCmd.Flags().Bool(enableDefaultCNI, false, "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \"--network-plugin=cni\".")
startCmd.Flags().Bool(waitUntilHealthy, true, "Wait until Kubernetes core services are healthy before exiting.")
startCmd.Flags().Bool(waitUntilHealthy, false, "Wait until Kubernetes core services are healthy before exiting.")
startCmd.Flags().Duration(waitTimeout, 6*time.Minute, "max time to wait per Kubernetes core services to be healthy.")
startCmd.Flags().Bool(nativeSSH, true, "Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.")
startCmd.Flags().Bool(autoUpdate, true, "If set, automatically updates drivers to the latest version. Defaults to true.")
}
// initKubernetesFlags inits the commandline flags for kubernetes related options
@ -182,7 +195,7 @@ func initKubernetesFlags() {
// initDriverFlags inits the commandline flags for vm drivers
func initDriverFlags() {
startCmd.Flags().String("vm-driver", "", fmt.Sprintf("Driver is one of: %v (defaults to virtualbox)", constants.SupportedVMDrivers))
startCmd.Flags().String("vm-driver", "", fmt.Sprintf("Driver is one of: %v (defaults to auto-detect)", driver.SupportedDrivers()))
startCmd.Flags().Bool(disableDriverMounts, false, "Disables the filesystem mounts provided by the hypervisors")
// kvm2
@ -257,17 +270,7 @@ func platform() string {
// runStart handles the executes the flow of "minikube start"
func runStart(cmd *cobra.Command, args []string) {
prefix := ""
if viper.GetString(cfg.MachineProfile) != constants.DefaultMachineName {
prefix = fmt.Sprintf("[%s] ", viper.GetString(cfg.MachineProfile))
}
versionState := out.Happy
if notify.MaybePrintUpdateTextFromGithub() {
versionState = out.Meh
}
out.T(versionState, "{{.prefix}}minikube {{.version}} on {{.platform}}", out.V{"prefix": prefix, "version": version.GetVersion(), "platform": platform()})
displayVersion(version.GetVersion())
displayEnviron(os.Environ())
// if --registry-mirror specified when run minikube start,
@ -286,30 +289,28 @@ func runStart(cmd *cobra.Command, args []string) {
exit.WithCodeT(exit.Data, "Unable to load config: {{.error}}", out.V{"error": err})
}
driver := selectDriver(oldConfig)
err = autoSetDriverOptions(driver)
driverName := selectDriver(oldConfig)
glog.Infof("selected: %v", driverName)
err = autoSetDriverOptions(cmd, driverName)
if err != nil {
glog.Errorf("Error autoSetOptions : %v", err)
}
validateFlags(driver)
validateUser(driver)
validateFlags(driverName)
validateUser(driverName)
v, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
} else if err := drivers.InstallOrUpdate(driver, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive)); err != nil {
out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driver, "error": err})
// No need to install a driver in download-only mode
if !viper.GetBool(downloadOnly) {
updateDriver(driverName)
}
k8sVersion, isUpgrade := getKubernetesVersion(oldConfig)
config, err := generateCfgFromFlags(cmd, k8sVersion, driver)
config, err := generateCfgFromFlags(cmd, k8sVersion, driverName)
if err != nil {
exit.WithError("Failed to generate config", err)
}
// For non-"none", the ISO is required to boot, so block until it is downloaded
if driver != constants.DriverNone {
if !driver.BareMetal(driverName) {
if err := cluster.CacheISO(config.MachineConfig); err != nil {
exit.WithError("Failed to cache ISO", err)
}
@ -336,7 +337,7 @@ func runStart(cmd *cobra.Command, args []string) {
mRunner, preExists, machineAPI, host := startMachine(&config)
defer machineAPI.Close()
// configure the runtime (docker, containerd, crio)
cr := configureRuntimes(mRunner, driver)
cr := configureRuntimes(mRunner, driverName, config.KubernetesConfig)
showVersionInfo(k8sVersion, cr)
waitCacheImages(&cacheGroup)
@ -352,20 +353,66 @@ func runStart(cmd *cobra.Command, args []string) {
// pull images or restart cluster
bootstrapCluster(bs, cr, mRunner, config.KubernetesConfig, preExists, isUpgrade)
configureMounts()
// enable addons with start command
enableAddons()
if err = loadCachedImagesInConfigFile(); err != nil {
out.T(out.FailureType, "Unable to load cached images from config file.")
}
// special ops for none driver, like change minikube directory.
if driver == constants.DriverNone {
// special ops for none , like change minikube directory.
if driverName == driver.None {
prepareNone()
}
if viper.GetBool(waitUntilHealthy) {
if err := bs.WaitCluster(config.KubernetesConfig, viper.GetDuration(waitTimeout)); err != nil {
exit.WithError("Wait failed", err)
waitCluster(bs, config)
if err := showKubectlInfo(kubeconfig, k8sVersion); err != nil {
glog.Errorf("kubectl info: %v", err)
}
}
func updateDriver(driverName string) {
v, err := version.GetSemverVersion()
if err != nil {
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
} else if err := driver.InstallOrUpdate(driverName, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive), viper.GetBool(autoUpdate)); err != nil {
out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driverName, "error": err})
}
}
func enableAddons() {
for _, a := range addonList {
err := cmdcfg.Set(a, "true")
if err != nil {
exit.WithError("addon enable failed", err)
}
}
showKubectlConnectInfo(kubeconfig)
}
func waitCluster(bs bootstrapper.Bootstrapper, config cfg.Config) {
var podsToWaitFor []string
if !viper.GetBool(waitUntilHealthy) {
// only wait for apiserver if wait=false
podsToWaitFor = []string{"apiserver"}
}
if err := bs.WaitForPods(config.KubernetesConfig, viper.GetDuration(waitTimeout), podsToWaitFor); err != nil {
exit.WithError("Wait failed", err)
}
}
func displayVersion(version string) {
prefix := ""
if viper.GetString(cfg.MachineProfile) != constants.DefaultMachineName {
prefix = fmt.Sprintf("[%s] ", viper.GetString(cfg.MachineProfile))
}
versionState := out.Happy
if notify.MaybePrintUpdateTextFromGithub() {
versionState = out.Meh
}
out.T(versionState, "{{.prefix}}minikube {{.version}} on {{.platform}}", out.V{"prefix": prefix, "version": version, "platform": platform()})
}
// displayEnviron makes the user aware of environment variables that will affect how minikube operates
@ -431,8 +478,12 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma
exit.WithError("Failed to get machine client", err)
}
host, preExists = startHost(m, config.MachineConfig)
runner, err = machine.CommandRunner(host)
if err != nil {
exit.WithError("Failed to get command runner", err)
}
ip := validateNetwork(host)
ip := validateNetwork(host, runner)
// Bypass proxy for minikube's vm host ip
err = proxy.ExcludeIP(ip)
if err != nil {
@ -443,10 +494,6 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma
if err := saveConfig(config); err != nil {
exit.WithError("Failed to save config", err)
}
runner, err = machine.CommandRunner(host)
if err != nil {
exit.WithError("Failed to get command runner", err)
}
return runner, preExists, m, host
}
@ -462,59 +509,115 @@ func showVersionInfo(k8sVersion string, cr cruntime.Manager) {
}
}
func showKubectlConnectInfo(kcs *kubeconfig.Settings) {
func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string) error {
if kcs.KeepContext {
out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName})
} else {
out.T(out.Ready, `Done! kubectl is now configured to use "{{.name}}"`, out.V{"name": cfg.GetMachineName()})
}
_, err := exec.LookPath("kubectl")
path, err := exec.LookPath("kubectl")
if err != nil {
out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/")
return nil
}
j, err := exec.Command(path, "version", "--client", "--output=json").Output()
if err != nil {
return errors.Wrap(err, "exec")
}
cv := struct {
ClientVersion struct {
GitVersion string `json:"gitVersion"`
} `json:"clientVersion"`
}{}
err = json.Unmarshal(j, &cv)
if err != nil {
return errors.Wrap(err, "unmarshal")
}
client, err := semver.Make(strings.TrimPrefix(cv.ClientVersion.GitVersion, version.VersionPrefix))
if err != nil {
return errors.Wrap(err, "client semver")
}
cluster := semver.MustParse(strings.TrimPrefix(k8sVersion, version.VersionPrefix))
minorSkew := int(math.Abs(float64(int(client.Minor) - int(cluster.Minor))))
glog.Infof("kubectl: %s, cluster: %s (minor skew: %d)", client, cluster, minorSkew)
if client.Major != cluster.Major || minorSkew > 1 {
out.WarningT("{{.path}} is version {{.client_version}}, and is incompatible with Kubernetes {{.cluster_version}}. You will need to update {{.path}} or use 'minikube kubectl' to connect with this cluster",
out.V{"path": path, "client_version": client, "cluster_version": cluster})
}
return nil
}
func selectDriver(oldConfig *cfg.Config) string {
driver := viper.GetString("vm-driver")
// By default, the driver is whatever we used last time
if driver == "" {
driver = constants.DefaultVMDriver
name := viper.GetString("vm-driver")
glog.Infof("selectDriver: flag=%q, old=%v", name, oldConfig)
if name == "" {
// By default, the driver is whatever we used last time
if oldConfig != nil {
driver = oldConfig.MachineConfig.VMDriver
return oldConfig.MachineConfig.VMDriver
}
options := driver.Choices()
pick, alts := driver.Choose(options)
if len(options) > 1 {
out.T(out.Sparkle, `Automatically selected the '{{.driver}}' driver (alternates: {{.alternates}})`, out.V{"driver": pick.Name, "alternates": alts})
} else {
out.T(out.Sparkle, `Automatically selected the '{{.driver}}' driver`, out.V{"driver": pick.Name})
}
if pick.Name == "" {
exit.WithCodeT(exit.Config, "Unable to determine a default driver to use. Try specifying --vm-driver, or see https://minikube.sigs.k8s.io/docs/start/")
}
name = pick.Name
}
if err := cmdcfg.IsValidDriver(runtime.GOOS, driver); err != nil {
exit.WithCodeT(exit.Failure, "The driver '{{.driver}}' is not supported on {{.os}}", out.V{"driver": driver, "os": runtime.GOOS})
if !driver.Supported(name) {
exit.WithCodeT(exit.Failure, "The driver '{{.driver}}' is not supported on {{.os}}", out.V{"driver": name, "os": runtime.GOOS})
}
st := driver.Status(name)
if st.Error != nil {
out.ErrLn("")
out.WarningT("'{{.driver}}' driver reported a possible issue: {{.error}}", out.V{"driver": name, "error": st.Error, "fix": st.Fix})
out.ErrT(out.Tip, "Suggestion: {{.fix}}", out.V{"fix": translate.T(st.Fix)})
if st.Doc != "" {
out.ErrT(out.Documentation, "Documentation: {{.url}}", out.V{"url": st.Doc})
}
out.ErrLn("")
}
// Detect if our driver conflicts with a previously created VM. If we run into any errors, just move on.
api, err := machine.NewAPIClient()
if err != nil {
glog.Infof("selectDriver NewAPIClient: %v", err)
return driver
return name
}
exists, err := api.Exists(cfg.GetMachineName())
if err != nil {
glog.Infof("selectDriver api.Exists: %v", err)
return driver
return name
}
if !exists {
return driver
return name
}
h, err := api.Load(cfg.GetMachineName())
if err != nil {
glog.Infof("selectDriver api.Load: %v", err)
return driver
return name
}
if h.Driver.DriverName() == driver || h.Driver.DriverName() == "not-found" {
return driver
if h.Driver.DriverName() == name || h.Driver.DriverName() == "not-found" {
return name
}
out.ErrT(out.Conflict, `The existing "{{.profile_name}}" VM that was created using the "{{.old_driver}}" driver, and is incompatible with the "{{.driver}}" driver.`,
out.V{"profile_name": cfg.GetMachineName(), "driver": driver, "old_driver": h.Driver.DriverName()})
out.V{"profile_name": cfg.GetMachineName(), "driver": name, "old_driver": h.Driver.DriverName()})
out.ErrT(out.Workaround, `To proceed, either:
1) Delete the existing VM using: '{{.command}} delete'
@ -552,9 +655,8 @@ func selectImageRepository(mirrorCountry string, k8sVersion string) (bool, strin
}
checkRepository := func(repo string) error {
podInfraContainerImage, _ := images.CachedImages(repo, k8sVersion)
ref, err := name.ParseReference(podInfraContainerImage, name.WeakValidation)
pauseImage := images.PauseImage(repo, k8sVersion)
ref, err := name.ParseReference(pauseImage, name.WeakValidation)
if err != nil {
return err
}
@ -585,7 +687,7 @@ func minikubeCmd() string {
}
// validerUser validates minikube is run by the recommended user (privileged or regular)
func validateUser(driver string) {
func validateUser(drvName string) {
u, err := user.Current()
if err != nil {
glog.Errorf("Error getting the current user: %v", err)
@ -594,15 +696,15 @@ func validateUser(driver string) {
useForce := viper.GetBool(force)
if driver == constants.DriverNone && u.Uid != "0" && !useForce {
exit.WithCodeT(exit.Permissions, `The "{{.driver_name}}" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}'.`, out.V{"driver_name": driver})
if driver.BareMetal(drvName) && u.Uid != "0" && !useForce {
exit.WithCodeT(exit.Permissions, `The "{{.driver_name}}" driver requires root privileges. Please run minikube using 'sudo minikube --vm-driver={{.driver_name}}'.`, out.V{"driver_name": drvName})
}
if driver == constants.DriverNone || u.Uid != "0" {
if driver.BareMetal(drvName) || u.Uid != "0" {
return
}
out.T(out.Stopped, `The "{{.driver_name}}" driver should not be used with root privileges.`, out.V{"driver_name": driver})
out.T(out.Stopped, `The "{{.driver_name}}" driver should not be used with root privileges.`, out.V{"driver_name": drvName})
out.T(out.Tip, "If you are running minikube within a VM, consider using --vm-driver=none:")
out.T(out.Documentation, " https://minikube.sigs.k8s.io/docs/reference/drivers/none/")
@ -619,23 +721,23 @@ func validateUser(driver string) {
}
// validateFlags validates the supplied flags against known bad combinations
func validateFlags(driver string) {
func validateFlags(drvName string) {
diskSizeMB := pkgutil.CalculateSizeInMB(viper.GetString(humanReadableDiskSize))
if diskSizeMB < pkgutil.CalculateSizeInMB(constants.MinimumDiskSize) && !viper.GetBool(force) {
exit.WithCodeT(exit.Config, "Requested disk size {{.requested_size}} is less than minimum of {{.minimum_size}}", out.V{"requested_size": diskSizeMB, "minimum_size": pkgutil.CalculateSizeInMB(constants.MinimumDiskSize)})
if diskSizeMB < pkgutil.CalculateSizeInMB(minimumDiskSize) && !viper.GetBool(force) {
exit.WithCodeT(exit.Config, "Requested disk size {{.requested_size}} is less than minimum of {{.minimum_size}}", out.V{"requested_size": diskSizeMB, "minimum_size": pkgutil.CalculateSizeInMB(minimumDiskSize)})
}
memorySizeMB := pkgutil.CalculateSizeInMB(viper.GetString(memory))
if memorySizeMB < pkgutil.CalculateSizeInMB(constants.MinimumMemorySize) && !viper.GetBool(force) {
exit.UsageT("Requested memory allocation {{.requested_size}} is less than the minimum allowed of {{.minimum_size}}", out.V{"requested_size": memorySizeMB, "minimum_size": pkgutil.CalculateSizeInMB(constants.MinimumMemorySize)})
if memorySizeMB < pkgutil.CalculateSizeInMB(minimumMemorySize) && !viper.GetBool(force) {
exit.UsageT("Requested memory allocation {{.requested_size}} is less than the minimum allowed of {{.minimum_size}}", out.V{"requested_size": memorySizeMB, "minimum_size": pkgutil.CalculateSizeInMB(minimumMemorySize)})
}
if memorySizeMB < pkgutil.CalculateSizeInMB(constants.DefaultMemorySize) && !viper.GetBool(force) {
if memorySizeMB < pkgutil.CalculateSizeInMB(defaultMemorySize) && !viper.GetBool(force) {
out.T(out.Notice, "Requested memory allocation ({{.memory}}MB) is less than the default memory allocation of {{.default_memorysize}}MB. Beware that minikube might not work correctly or crash unexpectedly.",
out.V{"memory": memorySizeMB, "default_memorysize": pkgutil.CalculateSizeInMB(constants.DefaultMemorySize)})
out.V{"memory": memorySizeMB, "default_memorysize": pkgutil.CalculateSizeInMB(defaultMemorySize)})
}
var cpuCount int
if driver == constants.DriverNone {
if driver.BareMetal(drvName) {
if cfg.GetMachineName() != constants.DefaultMachineName {
exit.WithCodeT(exit.Config, "The 'none' driver does not support multiple profiles: https://minikube.sigs.k8s.io/docs/reference/drivers/none/")
}
@ -650,8 +752,8 @@ func validateFlags(driver string) {
} else {
cpuCount = viper.GetInt(cpus)
}
if cpuCount < constants.MinimumCPUS {
exit.UsageT("Requested CPU count {{.requested_cpus}} is less than the minimum allowed of {{.minimum_cpus}}", out.V{"requested_cpus": cpuCount, "minimum_cpus": constants.MinimumCPUS})
if cpuCount < minimumCPUS && !viper.GetBool(force) {
exit.UsageT("Requested cpu count {{.requested_cpus}} is less than the minimum allowed of {{.minimum_cpus}}", out.V{"requested_cpus": cpuCount, "minimum_cpus": minimumCPUS})
}
// check that kubeadm extra args contain only whitelisted parameters
@ -710,7 +812,7 @@ func waitCacheImages(g *errgroup.Group) {
}
// generateCfgFromFlags generates cfg.Config based on flags and supplied arguments
func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string) (cfg.Config, error) {
func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, drvName string) (cfg.Config, error) {
r, err := cruntime.New(cruntime.Config{Type: viper.GetString(containerRuntime)})
if err != nil {
return cfg.Config{}, err
@ -727,23 +829,8 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string)
}
// Feed Docker our host proxy environment by default, so that it can pull images
if _, ok := r.(*cruntime.Docker); ok {
if !cmd.Flags().Changed("docker-env") {
for _, k := range proxy.EnvVars {
if v := os.Getenv(k); v != "" {
// convert https_proxy to HTTPS_PROXY for linux
// TODO (@medyagh): if user has both http_proxy & HTTPS_PROXY set merge them.
k = strings.ToUpper(k)
if k == "HTTP_PROXY" || k == "HTTPS_PROXY" {
if strings.HasPrefix(v, "localhost") || strings.HasPrefix(v, "127.0") {
out.WarningT("Not passing {{.name}}={{.value}} to docker env.", out.V{"name": k, "value": v})
continue
}
}
dockerEnv = append(dockerEnv, fmt.Sprintf("%s=%s", k, v))
}
}
}
if _, ok := r.(*cruntime.Docker); ok && !cmd.Flags().Changed("docker-env") {
setDockerProxy()
}
repository := viper.GetString(imageRepository)
@ -765,7 +852,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string)
repository = autoSelectedRepository
}
if repository != "" {
if cmd.Flags().Changed(imageRepository) {
out.T(out.SuccessType, "Using image repository {{.name}}", out.V{"name": repository})
}
@ -777,7 +864,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string)
Memory: pkgutil.CalculateSizeInMB(viper.GetString(memory)),
CPUs: viper.GetInt(cpus),
DiskSize: pkgutil.CalculateSizeInMB(viper.GetString(humanReadableDiskSize)),
VMDriver: driver,
VMDriver: drvName,
ContainerRuntime: viper.GetString(containerRuntime),
HyperkitVpnKitSock: viper.GetString(vpnkitSock),
HyperkitVSockPorts: viper.GetStringSlice(vsockPorts),
@ -822,13 +909,33 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string)
return cfg, nil
}
// autoSetDriverOptions sets the options needed for specific vm-driver automatically.
func autoSetDriverOptions(driver string) error {
if driver == constants.DriverNone {
if o := none.AutoOptions(); o != "" {
return extraOptions.Set(o)
// setDockerProxy sets the proxy environment variables in the docker environment.
func setDockerProxy() {
for _, k := range proxy.EnvVars {
if v := os.Getenv(k); v != "" {
// convert https_proxy to HTTPS_PROXY for linux
// TODO (@medyagh): if user has both http_proxy & HTTPS_PROXY set merge them.
k = strings.ToUpper(k)
if k == "HTTP_PROXY" || k == "HTTPS_PROXY" {
if strings.HasPrefix(v, "localhost") || strings.HasPrefix(v, "127.0") {
out.WarningT("Not passing {{.name}}={{.value}} to docker env.", out.V{"name": k, "value": v})
continue
}
}
dockerEnv = append(dockerEnv, fmt.Sprintf("%s=%s", k, v))
}
viper.Set(cacheImages, false)
}
}
// autoSetDriverOptions sets the options needed for specific vm-driver automatically.
func autoSetDriverOptions(cmd *cobra.Command, drvName string) error {
hints := driver.FlagDefaults(drvName)
if !cmd.Flags().Changed("extra-config") && hints.ExtraOptions != "" {
return extraOptions.Set(hints.ExtraOptions)
}
if !cmd.Flags().Changed(cacheImages) {
viper.Set(cacheImages, hints.CacheImages)
}
return nil
}
@ -888,7 +995,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) {
}
// validateNetwork tries to catch network problems as soon as possible
func validateNetwork(h *host.Host) string {
func validateNetwork(h *host.Host, r command.Runner) string {
ip, err := h.Driver.GetIP()
if err != nil {
exit.WithError("Unable to get VM IP address", err)
@ -912,10 +1019,64 @@ func validateNetwork(h *host.Host) string {
}
}
// Here is where we should be checking connectivity to/from the VM
if !driver.BareMetal(h.Driver.DriverName()) {
trySSH(h, ip)
}
tryLookup(r)
tryRegistry(r)
return ip
}
func trySSH(h *host.Host, ip string) {
sshAddr := fmt.Sprintf("%s:22", ip)
conn, err := net.Dial("tcp", sshAddr)
if err != nil {
exit.WithCodeT(exit.IO, `minikube is unable to connect to the VM: {{.error}}
This is likely due to one of two reasons:
- VPN or firewall interference
- {{.hypervisor}} network configuration issue
Suggested workarounds:
- Disable your local VPN or firewall software
- Configure your local VPN or firewall to allow access to {{.ip}}
- Restart or reinstall {{.hypervisor}}
- Use an alternative --vm-driver`, out.V{"error": err, "hypervisor": h.Driver.DriverName(), "ip": ip})
}
defer conn.Close()
}
func tryLookup(r command.Runner) {
// DNS check
if rr, err := r.RunCmd(exec.Command("nslookup", "kubernetes.io")); err != nil {
glog.Warningf("%s failed: %v", rr.Args, err)
out.WarningT("VM may be unable to resolve external DNS records")
}
}
func tryRegistry(r command.Runner) {
// Try an HTTPS connection to the image repository
proxy := os.Getenv("HTTPS_PROXY")
opts := []string{"-sS"}
if proxy != "" && !strings.HasPrefix(proxy, "localhost") && !strings.HasPrefix(proxy, "127.0") {
opts = append([]string{"-x", proxy}, opts...)
}
repo := viper.GetString(imageRepository)
if repo == "" {
repo = images.DefaultImageRepo
}
opts = append(opts, fmt.Sprintf("https://%s/", repo))
if rr, err := r.RunCmd(exec.Command("curl", opts...)); err != nil {
glog.Warningf("%s failed: %v", rr.Args, err)
out.WarningT("VM is unable to access {{.repository}}, you may need to configure a proxy or set --image-repository", out.V{"repository": repo})
}
}
// getKubernetesVersion ensures that the requested version is reasonable
func getKubernetesVersion(old *cfg.Config) (string, bool) {
rawVersion := viper.GetString(kubernetesVersion)
@ -993,15 +1154,15 @@ func setupKubeAdm(mAPI libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Boo
}
// configureRuntimes does what needs to happen to get a runtime going.
func configureRuntimes(runner cruntime.CommandRunner, driver string) cruntime.Manager {
config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner}
func configureRuntimes(runner cruntime.CommandRunner, drvName string, k8s cfg.KubernetesConfig) cruntime.Manager {
config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner, ImageRepository: k8s.ImageRepository, KubernetesVersion: k8s.KubernetesVersion}
cr, err := cruntime.New(config)
if err != nil {
exit.WithError("Failed runtime", err)
}
disableOthers := true
if driver == constants.DriverNone {
if driver.BareMetal(drvName) {
disableOthers = false
}
err = cr.Enable(disableOthers)

View File

@ -26,8 +26,8 @@ import (
)
func TestGenerateCfgFromFlagsHTTPProxyHandling(t *testing.T) {
viper.SetDefault(memory, constants.DefaultMemorySize)
viper.SetDefault(humanReadableDiskSize, constants.DefaultDiskSize)
viper.SetDefault(memory, defaultMemorySize)
viper.SetDefault(humanReadableDiskSize, defaultDiskSize)
originalEnv := os.Getenv("HTTP_PROXY")
defer func() {
err := os.Setenv("HTTP_PROXY", originalEnv)

View File

@ -17,7 +17,10 @@ limitations under the License.
package cmd
import (
"encoding/json"
"fmt"
"os"
"strings"
"text/template"
"github.com/docker/machine/libmachine/state"
@ -35,6 +38,16 @@ import (
)
var statusFormat string
var output string
// KubeconfigStatus represents the kubeconfig status
var KubeconfigStatus = struct {
Configured string
Misconfigured string
}{
Configured: `Configured`,
Misconfigured: `Misconfigured`,
}
// Status represents the status
type Status struct {
@ -48,6 +61,11 @@ const (
minikubeNotRunningStatusFlag = 1 << 0
clusterNotRunningStatusFlag = 1 << 1
k8sNotRunningStatusFlag = 1 << 2
defaultStatusFormat = `host: {{.Host}}
kubelet: {{.Kubelet}}
apiserver: {{.APIServer}}
kubeconfig: {{.Kubeconfig}}
`
)
// statusCmd represents the status command
@ -58,6 +76,11 @@ var statusCmd = &cobra.Command{
Exit status contains the status of minikube's VM, cluster and kubernetes encoded on it's bits in this order from right to left.
Eg: 7 meaning: 1 (for minikube NOK) + 2 (for cluster NOK) + 4 (for kubernetes NOK)`,
Run: func(cmd *cobra.Command, args []string) {
if output != "text" && statusFormat != defaultStatusFormat {
exit.UsageT("Cannot use both --output and --format options")
}
var returnCode = 0
api, err := machine.NewAPIClient()
if err != nil {
@ -110,10 +133,9 @@ var statusCmd = &cobra.Command{
glog.Errorln("Error kubeconfig status:", err)
}
if ks {
kubeconfigSt = "Correctly Configured: pointing to minikube-vm at " + ip.String()
kubeconfigSt = KubeconfigStatus.Configured
} else {
kubeconfigSt = "Misconfigured: pointing to stale minikube-vm." +
"\nTo fix the kubectl context, run minikube update-context"
kubeconfigSt = KubeconfigStatus.Misconfigured
returnCode |= k8sNotRunningStatusFlag
}
} else {
@ -126,13 +148,14 @@ var statusCmd = &cobra.Command{
APIServer: apiserverSt,
Kubeconfig: kubeconfigSt,
}
tmpl, err := template.New("status").Parse(statusFormat)
if err != nil {
exit.WithError("Error creating status template", err)
}
err = tmpl.Execute(os.Stdout, status)
if err != nil {
exit.WithError("Error executing status template", err)
switch strings.ToLower(output) {
case "text":
printStatusText(status)
case "json":
printStatusJSON(status)
default:
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'text', 'json'", output))
}
os.Exit(returnCode)
@ -140,7 +163,32 @@ var statusCmd = &cobra.Command{
}
func init() {
statusCmd.Flags().StringVar(&statusFormat, "format", constants.DefaultStatusFormat,
statusCmd.Flags().StringVarP(&statusFormat, "format", "f", defaultStatusFormat,
`Go template format string for the status output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
For the list accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd#Status`)
statusCmd.Flags().StringVarP(&output, "output", "o", "text",
`minikube status --output OUTPUT. json, text`)
}
var printStatusText = func(status Status) {
tmpl, err := template.New("status").Parse(statusFormat)
if err != nil {
exit.WithError("Error creating status template", err)
}
err = tmpl.Execute(os.Stdout, status)
if err != nil {
exit.WithError("Error executing status template", err)
}
if status.Kubeconfig == KubeconfigStatus.Misconfigured {
out.WarningT("Warning: Your kubectl is pointing to stale minikube-vm.\nTo fix the kubectl context, run `minikube update-context`")
}
}
var printStatusJSON = func(status Status) {
jsonString, err := json.Marshal(status)
if err != nil {
exit.WithError("Error converting status to json", err)
}
out.String(string(jsonString))
}

View File

@ -77,7 +77,7 @@ func runStop(cmd *cobra.Command, args []string) {
}
machineName := pkg_config.GetMachineName()
err = kubeconfig.UnsetCurrentContext(constants.KubeconfigPath, machineName)
err = kubeconfig.UnsetCurrentContext(machineName, constants.KubeconfigPath)
if err != nil {
exit.WithError("update config", err)
}

View File

@ -18,7 +18,6 @@ package cmd
import (
"github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/notify"
"k8s.io/minikube/pkg/minikube/out"
@ -29,12 +28,8 @@ var updateCheckCmd = &cobra.Command{
Use: "update-check",
Short: "Print current and latest version number",
Long: `Print current and latest version number`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Explicitly disable update checking for the version command
enableUpdateNotification = false
},
Run: func(command *cobra.Command, args []string) {
url := constants.GithubMinikubeReleasesURL
url := notify.GithubMinikubeReleasesURL
r, err := notify.GetAllVersionsFromURL(url)
if err != nil {
exit.WithError("Unable to fetch latest version info", err)

View File

@ -44,7 +44,7 @@ var updateContextCmd = &cobra.Command{
if err != nil {
exit.WithError("Error host driver ip status", err)
}
updated, err := kubeconfig.UpdateIP(ip, constants.KubeconfigPath, machineName)
updated, err := kubeconfig.UpdateIP(ip, machineName, constants.KubeconfigPath)
if err != nil {
exit.WithError("update config", err)
}

View File

@ -26,10 +26,6 @@ var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version of minikube",
Long: `Print the version of minikube.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
// Explicitly disable update checking for the version command
enableUpdateNotification = false
},
Run: func(command *cobra.Command, args []string) {
out.Ln("minikube version: %v", version.GetVersion())
gitCommitID := version.GetGitCommitID()

View File

@ -28,6 +28,9 @@ import (
// Fix for https://github.com/kubernetes/minikube/issues/4866
_ "k8s.io/minikube/pkg/initflag"
// Register drivers
_ "k8s.io/minikube/pkg/minikube/registry/drvs"
mlog "github.com/docker/machine/libmachine/log"
"github.com/golang/glog"
@ -42,7 +45,9 @@ import (
const minikubeEnableProfile = "MINIKUBE_ENABLE_PROFILING"
var (
machineLogErrorRe = regexp.MustCompile(`(?i) (failed|error|fatal)`)
// This regex is intentionally very specific, it's supposed to surface
// unexpected errors from libmachine to the user.
machineLogErrorRe = regexp.MustCompile(`VirtualizationException`)
machineLogWarningRe = regexp.MustCompile(`(?i)warning`)
)
@ -67,6 +72,7 @@ func bridgeLogMessages() {
log.SetOutput(stdLogBridge{})
mlog.SetErrWriter(machineLogBridge{})
mlog.SetOutWriter(machineLogBridge{})
mlog.SetDebug(true)
}
type stdLogBridge struct{}

View File

@ -0,0 +1,49 @@
/*
Copyright 2017 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 cmd
import (
"errors"
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "mkcmp [path to first binary] [path to second binary]",
Short: "mkcmp is used to compare performance of two minikube binaries",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return validateArgs(args)
},
Run: func(cmd *cobra.Command, args []string) {},
}
func validateArgs(args []string) error {
if len(args) != 2 {
return errors.New("mkcmp requires two minikube binaries to compare: mkcmp [path to first binary] [path to second binary]")
}
return nil
}
// Execute runs the mkcmp command
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors All rights reserved.
Copyright 2017 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.
@ -14,4 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package virtualbox
package main
import "k8s.io/minikube/cmd/performance/cmd"
func main() {
cmd.Execute()
}

View File

@ -24,50 +24,28 @@ spec:
hostPID: true
containers:
- name: gvisor
image: {{default "gcr.io/k8s-minikube" .ImageRepository}}/gvisor-addon:latest
image: {{default "gcr.io/k8s-minikube" .ImageRepository}}/gvisor-addon:2
securityContext:
privileged: true
volumeMounts:
- mountPath: /node/
name: node
- mountPath: /usr/libexec/sudo
name: sudo
- mountPath: /var/run
name: varrun
- mountPath: /usr/bin
name: usrbin
- mountPath: /usr/lib
name: usrlib
- mountPath: /bin
name: bin
name: node-root
- mountPath: /node/run
name: node-run
- mountPath: /tmp/gvisor
name: gvisor
name: node-tmp
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/node/bin
- name: SYSTEMD_IGNORE_CHROOT
value: "yes"
imagePullPolicy: IfNotPresent
volumes:
- name: node
- name: node-root
hostPath:
path: /
- name: sudo
- name: node-run
hostPath:
path: /usr/libexec/sudo
- name: varrun
hostPath:
path: /var/run
- name: usrlib
hostPath:
path: /usr/lib
- name: usrbin
hostPath:
path: /usr/bin
- name: bin
hostPath:
path: /bin
- name: gvisor
path: /run
- name: node-tmp
hostPath:
path: /tmp/gvisor
restartPolicy: Always

View File

@ -1,54 +0,0 @@
# Copyright 2017 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.
apiVersion: v1
kind: ReplicationController
metadata:
labels:
k8s-app: heapster
kubernetes.io/minikube-addons: heapster
addonmanager.kubernetes.io/mode: Reconcile
version: v1.5.3
name: heapster
namespace: kube-system
spec:
replicas: 1
selector:
k8s-app: heapster
version: v1.5.3
addonmanager.kubernetes.io/mode: Reconcile
template:
metadata:
labels:
k8s-app: heapster
version: v1.5.3
addonmanager.kubernetes.io/mode: Reconcile
spec:
containers:
- name: heapster
image: {{default "k8s.gcr.io" .ImageRepository}}/heapster-{{.Arch}}:v1.5.3
imagePullPolicy: IfNotPresent
command:
- /heapster
- --source=kubernetes.summary_api:''
- --sink=influxdb:http://monitoring-influxdb:8086
- --metric_resolution=60s
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs
readOnly: true
volumes:
- name: ssl-certs
hostPath:
path: /etc/ssl/certs

View File

@ -1,75 +0,0 @@
# Copyright 2017 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.
apiVersion: v1
kind: ReplicationController
metadata:
name: influxdb-grafana
labels:
k8s-app: influx-grafana
kubernetes.io/minikube-addons: heapster
addonmanager.kubernetes.io/mode: Reconcile
namespace: kube-system
spec:
replicas: 1
selector:
k8s-app: influx-grafana
addonmanager.kubernetes.io/mode: Reconcile
template:
metadata:
labels:
k8s-app: influx-grafana
addonmanager.kubernetes.io/mode: Reconcile
spec:
containers:
- name: influxdb
image: {{default "k8s.gcr.io" .ImageRepository}}/heapster-influxdb-{{.Arch}}:v1.3.3
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8083
- name: api
containerPort: 8086
volumeMounts:
- mountPath: /data
name: influxdb-storage
- name: grafana
image: {{default "k8s.gcr.io" .ImageRepository}}/heapster-grafana-{{.Arch}}:v4.4.3
imagePullPolicy: IfNotPresent
env:
- name: INFLUXDB_SERVICE_URL
value: http://localhost:8086
# The following env variables are required to make Grafana accessible via
# the kubernetes api-server proxy. On production clusters, we recommend
# removing these env variables, setup auth for grafana, and expose the grafana
# service using a LoadBalancer or a public IP.
- name: GF_AUTH_BASIC_ENABLED
value: "false"
- name: GF_AUTH_ANONYMOUS_ENABLED
value: "true"
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
value: Admin
- name: GF_SERVER_ROOT_URL
value: /
ports:
- name: ui
containerPort: 3000
volumeMounts:
- mountPath: /var
name: grafana-storage
volumes:
- name: influxdb-storage
emptyDir: {}
- name: grafana-storage
emptyDir: {}

View File

@ -1,34 +0,0 @@
# Copyright 2017 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.
apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/name: monitoring-influxdb
kubernetes.io/minikube-addons: heapster
addonmanager.kubernetes.io/mode: Reconcile
name: monitoring-influxdb
namespace: kube-system
spec:
ports:
- name: http
port: 8083
targetPort: 8083
- name: api
port: 8086
targetPort: 8086
selector:
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: influx-grafana

View File

@ -0,0 +1,23 @@
## helm-tiller Addon
[Kubernetes Helm](https://helm.sh) - The Kubernetes Package Manager
### Enabling helm-tiller
To enable this addon, simply run:
```shell script
minikube addons enable helm-tiller
```
In a minute or so tiller will be installed into your cluster. You could run `helm init` each time you create a new minikube instance or you could just enable this addon.
Each time you start a new minikube instance, tiller will be automatically installed.
### Testing installation
```shell script
helm ls
```
If everything went well you shouldn't get any errors about tiller being installed in your cluster. If you haven't deployed any releases `helm ls` won't return anything.
### Deprecation of Tiller
When tiller is finally deprecated this addon won't be necessary anymore. If your version of helm doesn't use tiller, you don't need this addon.

View File

@ -0,0 +1,83 @@
# Copyright 2019 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: helm
name: tiller
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/minikube-addons: helm
name: tiller-deploy
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: helm
name: tiller
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app: helm
name: tiller
spec:
automountServiceAccountToken: true
containers:
- env:
- name: TILLER_NAMESPACE
value: kube-system
- name: TILLER_HISTORY_MAX
value: "0"
image: gcr.io/kubernetes-helm/tiller:v2.14.3
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /liveness
port: 44135
scheme: HTTP
initialDelaySeconds: 1
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: tiller
ports:
- containerPort: 44134
name: tiller
protocol: TCP
- containerPort: 44135
name: http
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readiness
port: 44135
scheme: HTTP
initialDelaySeconds: 1
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
serviceAccount: tiller
serviceAccountName: tiller

View File

@ -1,4 +1,4 @@
# Copyright 2017 The Kubernetes Authors All rights reserved.
# Copyright 2019 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,22 +13,30 @@
# limitations under the License.
apiVersion: v1
kind: Service
kind: ServiceAccount
metadata:
labels:
kubernetes.io/name: monitoring-grafana
kubernetes.io/minikube-addons: heapster
kubernetes.io/minikube-addons-endpoint: heapster
addonmanager.kubernetes.io/mode: Reconcile
name: monitoring-grafana
name: tiller
namespace: kube-system
spec:
type: NodePort
ports:
- port: 80
nodePort: 30002
protocol: TCP
targetPort: ui
selector:
labels:
app: helm
name: tiller
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: influx-grafana
kubernetes.io/minikube-addons: helm
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: tiller-clusterrolebinding
labels:
app: helm
name: tiller
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/minikube-addons: helm
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: ""

View File

@ -1,4 +1,4 @@
# Copyright 2017 The Kubernetes Authors All rights reserved.
# Copyright 2019 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -16,16 +16,19 @@ apiVersion: v1
kind: Service
metadata:
labels:
kubernetes.io/name: heapster
kubernetes.io/minikube-addons: heapster
app: helm
name: tiller
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/minikube-addons-endpoint: heapster
name: heapster
kubernetes.io/minikube-addons: helm
name: tiller-deploy
namespace: kube-system
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8082
- name: tiller
port: 44134
protocol: TCP
targetPort: tiller
selector:
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: heapster
app: helm
name: tiller

View File

@ -0,0 +1,175 @@
# Minikube Ingress DNS
![Build Status](https://gitlab.com/cryptexlabs/public/development/minikube-ingress-dns/badges/master/pipeline.svg)
DNS service for ingress controllers running on your minikube server
## Overview
### Problem
When running minikube locally you are highly likely to want to run your services on an ingress controller so that you
don't have to use minikube tunnel or NodePorts to access your services. While NodePort might be ok in a lot of
circumstances in order to test some features an ingress is necessary. Ingress controllers are great because you can
define your entire architecture in something like a helm chart and all your services will be available. There is only
1 problem. That is that your ingress controller works basically off of dns and while running minikube that means that
your local dns names like `myservice.test` will have to resolve to `$(minikube ip)` not really a big deal except the
only real way to do this is to add an entry for every service in your `/etc/hosts` file. This gets messy for obvious
reasons. If you have a lot of services running that each have their own dns entry then you have to set those up
manually. Even if you automate it you then need to rely on the host operating system storing configurations instead of
storing them in your cluster. To make it worse it has to be constantly maintained and updated as services are added,
remove, and renamed. I call it the `/ets/hosts` pollution problem.
### Solution
What if you could just access your local services magically without having to edit your `/etc/hosts` file? Well now you
can. This addon acts as a DNS service that runs inside your kubernetes cluster. All you have to do is install the
service and add the `$(minikube ip)` as a DNS server on your host machine. Each time the dns service is queried an
API call is made to the kubernetes master service for a list of all the ingresses. If a match is found for the name a
response is given with an IP address as the `$(minikube ip)`. So for example lets say my minikube ip address is
`192.168.99.106` and I have an ingress controller with the name of `myservice.test` then I would get a result like so:
```text
#bash:~$ nslookup myservice.test $(minikube ip)
Server: 192.168.99.169
Address: 192.168.99.169#53
Non-authoritative answer:
Name: myservice.test $(minikube ip)
Address: 192.168.99.169
```
## Installation
### Start minikube
```
minikube start
```
### Install the kubernetes resources
```bash
minikube addons enable ingress-dns
```
### Add the minikube ip as a dns server
#### Mac OS
Create a file in `/etc/resolver/minikube-profilename-test`
```
domain test
nameserver 192.168.99.169
search_order 1
timeout 5
```
Replace `192.168.99.169` with your minikube ip and `profilename` is the name of the minikube profile for the
corresponding ip address
If you have multiple minikube ips you must configure multiple files
See https://www.unix.com/man-page/opendarwin/5/resolver/
Note that even though the `port` feature is documented. It does not actually work.
#### Linux
Update the file `/etc/resolvconf/resolv.conf.d/base` to have the following contents
```
search test
nameserver 192.168.99.169
timeout 5
```
Replace `192.168.99.169` with your minikube ip
If your linux OS uses `systemctl` run the following commands
```bash
sudo resolvconf -u
systemctl disable --now resolvconf.service
```
If your linux does not use `systemctl` run the following commands
TODO add supporting docs for Linux OS that do not use `systemctl`
See https://linux.die.net/man/5/resolver
#### Windows
TODO
## Testing
### Add the test ingress
```bash
kubectl apply -f https://github.com/kubernetes/minikube/blob/master/deploy/addons/ingress-dns/example/example.yaml
```
Note: Minimum Kubernetes version for example ingress is 1.14.7
### Validate DNS queries are returning A records
```bash
nslookup hello-john.test $(minikube ip)
nslookup hello-jane.test $(minikube ip)
```
### Validate domain names are resolving on host OS
```bash
ping hello-john.test
```
Expected results:
```text
PING hello-john.test (192.168.99.169): 56 data bytes
64 bytes from 192.168.99.169: icmp_seq=0 ttl=64 time=0.361 ms
```
```bash
ping hello-jane.test
```
```text
PING hello-jane.test (192.168.99.169): 56 data bytes
64 bytes from 192.168.99.169: icmp_seq=0 ttl=64 time=0.262 ms
```
### Curl the example server
```bash
curl http://hello-john.test
```
Expected result:
```text
Hello, world!
Version: 1.0.0
Hostname: hello-world-app-557ff7dbd8-64mtv
```
```bash
curl http://hello-jane.test
```
Expected result:
```text
Hello, world!
Version: 1.0.0
Hostname: hello-world-app-557ff7dbd8-64mtv
```
## Known issues
### .localhost domains will not resolve on chromium
.localhost domains will not correctly resolve on chromium since it is used as a loopback address. Instead use .test, .example, or .invalid
### .local is a reserved TLD
Do not use .local as this is a reserved TLD for mDNS and bind9 DNS servers
### Mac OS
#### mDNS reloading
Each time a file is created or a change is made to a file in `/etc/resolver` you may need to run the following to reload Mac OS mDNS resolver.
```bash
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
```
## TODO
- Add a service that runs on the host OS which will update the files in `/etc/resolver` automatically
- Start this service when running `minikube addons enable ingress-dns` and stop the service when running
`minikube addons disable ingress-dns`
## Contributors
- [Josh Woodcock](https://github.com/woodcockjosh)
## Images used in this plugin
| Image | Source | Owner |
| :--- | :--- | :--- |
| [nginx-ingress](https://hub.docker.com/r/nginx/nginx-ingress) | [ingress-nginx](https://github.com/kubernetes/ingress-nginx) | Nginx
| [minikube-ingress-dns](https://hub.docker.com/r/cryptexlabs/minikube-ingress-dns) | [minikube-ingress-dns](https://gitlab.com/cryptexlabs/public/development/minikube-ingress-dns) | Cryptex Labs

View File

@ -0,0 +1,82 @@
# Copyright 2016 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.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-app
namespace: default
spec:
selector:
matchLabels:
app: hello-world-app
template:
metadata:
labels:
app: hello-world-app
spec:
containers:
- name: hello-world-app
image: gcr.io/google-samples/hello-app:1.0
ports:
- containerPort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
namespace: kube-system
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello-john.test
http:
paths:
- path: /|/(.+)
backend:
serviceName: hello-world-app
servicePort: 80
- host: hello-jane.test
http:
paths:
- path: /|/(.+)
backend:
serviceName: hello-world-app
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-app
namespace: kube-system
spec:
type: ExternalName
externalName: hello-world-app.default.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-app
namespace: default
spec:
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
type: NodePort
selector:
app: hello-world-app

View File

@ -0,0 +1,93 @@
# Copyright 2016 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.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: minikube-ingress-dns
namespace: kube-system
labels:
app: minikube-ingress-dns
kubernetes.io/bootstrapping: rbac-defaults
app.kubernetes.io/part-of: kube-system
addonmanager.kubernetes.io/mode: Reconcile
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: minikube-ingress-dns
namespace: kube-system
labels:
app: minikube-ingress-dns
kubernetes.io/bootstrapping: rbac-defaults
app.kubernetes.io/part-of: kube-system
addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
- ""
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: minikube-ingress-dns
namespace: kube-system
labels:
app: minikube-ingress-dns
kubernetes.io/bootstrapping: rbac-defaults
app.kubernetes.io/part-of: kube-system
addonmanager.kubernetes.io/mode: Reconcile
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: minikube-ingress-dns
subjects:
- kind: ServiceAccount
name: minikube-ingress-dns
namespace: kube-system
---
apiVersion: v1
kind: Pod
metadata:
name: kube-ingress-dns-minikube
namespace: kube-system
labels:
app: minikube-ingress-dns
app.kubernetes.io/part-of: kube-system
addonmanager.kubernetes.io/mode: Reconcile
spec:
serviceAccountName: minikube-ingress-dns
hostNetwork: true
containers:
- name: minikube-ingress-dns
image: "cryptexlabs/minikube-ingress-dns:0.2.0"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 53
protocol: UDP
env:
- name: DNS_PORT
value: "53"
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP

View File

@ -24,6 +24,12 @@ metadata:
addonmanager.kubernetes.io/mode: Reconcile
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
# maxUnavailable needs to be 1 so that port conflicts between the old and new pod doesn't happen when using hostPort
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: nginx-ingress-controller
@ -42,7 +48,7 @@ spec:
serviceAccountName: nginx-ingress
terminationGracePeriodSeconds: 60
containers:
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller{{.ExoticArch}}:0.25.1
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller{{.ExoticArch}}:0.26.1
name: nginx-ingress-controller
imagePullPolicy: IfNotPresent
readinessProbe:

View File

@ -0,0 +1,5 @@
{{ define "main" }}
<div style="padding-top:20px">
{{ .Render "content" }}
</div>
{{ end }}

View File

@ -0,0 +1,5 @@
{{ define "main" }}
<div style="padding-top:20px">
{{ .Render "content" }}
</div>
{{ end }}

View File

@ -0,0 +1,5 @@
{{ define "main" }}
<div style="padding-top:60px">
{{ .Render "content" }}
</div>
{{ end }}

View File

@ -0,0 +1,5 @@
{{ define "main" }}
<div style="padding-top:20px">
{{ .Render "content" }}
</div>
{{ end }}

View File

@ -1,27 +1,24 @@
apiVersion: v1
kind: ReplicationController
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry-creds
namespace: kube-system
labels:
version: v1.9
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/minikube-addons: registry-creds
spec:
replicas: 1
selector:
name: registry-creds
version: v1.9
addonmanager.kubernetes.io/mode: Reconcile
matchLabels:
name: registry-creds
template:
metadata:
labels:
name: registry-creds
version: v1.9
addonmanager.kubernetes.io/mode: Reconcile
spec:
containers:
- image: registry.hub.docker.com/upmcenterprises/registry-creds:1.9
- image: upmcenterprises/registry-creds:1.9
name: registry-creds
imagePullPolicy: Always
env:

View File

@ -12,9 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM ubuntu:18.04
RUN apt-get update && \
apt-get install -y kmod gcc wget xz-utils libc6-dev bc libelf-dev bison flex openssl libssl-dev libidn2-0 sudo libcap2 && \
rm -rf /var/lib/apt/lists/*
# Need an image with chroot
FROM alpine:3
COPY out/gvisor-addon /gvisor-addon
CMD ["/gvisor-addon"]

View File

@ -2,4 +2,4 @@ default 1
label 1
kernel /boot/bzImage
initrd /boot/initrd
append root=/dev/sr0 loglevel=3 console=ttyS0 noembed nomodeset norestore waitusb=10 systemd.legacy_systemd_cgroup_controller=yes
append root=/dev/sr0 loglevel=3 console=ttyS0 noembed nomodeset norestore waitusb=10 random.trust_cpu=on hw_rng_model=virtio systemd.legacy_systemd_cgroup_controller=yes

View File

@ -8,11 +8,11 @@ machine=$(uname -m)
case ${machine} in
aarch64 )
TOOLBOX_DOCKER_IMAGE=arm64v8/fedora
TOOLBOX_DOCKER_TAG=29
TOOLBOX_DOCKER_TAG=latest
;;
x86_64 )
TOOLBOX_DOCKER_IMAGE=fedora
TOOLBOX_DOCKER_TAG=29
TOOLBOX_DOCKER_TAG=latest
;;
* )
echo "Warning: Unknown machine type ${machine}" >&2
@ -69,10 +69,9 @@ if [ "x${1-}" == x-c ]; then
set /bin/sh "$@"
fi
sudo systemd-nspawn \
sudo SYSTEMD_NSPAWN_SHARE_SYSTEM=1 systemd-nspawn \
--directory="${machinepath}" \
--capability=all \
--share-system \
${TOOLBOX_BIND} \
${TOOLBOX_ENV} \
--user="${TOOLBOX_USER}" "$@"

View File

@ -1 +1 @@
docker -1 docker -1 =tcuser /home/docker /bin/bash wheel,vboxsf -
docker 1000 docker 1000 =tcuser /home/docker /bin/bash wheel,vboxsf -

View File

@ -3,7 +3,7 @@ BR2_CCACHE=y
BR2_OPTIMIZE_2=y
BR2_TOOLCHAIN_BUILDROOT_VENDOR="minikube"
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_15=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_19=y
BR2_BINUTILS_VERSION_2_30_X=y
BR2_GCC_VERSION_7_X=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
@ -18,8 +18,6 @@ BR2_SYSTEM_BIN_SH_BASH=y
BR2_ROOTFS_USERS_TABLES="$(BR2_EXTERNAL_MINIKUBE_PATH)/board/coreos/minikube/users"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_MINIKUBE_PATH)/board/coreos/minikube/rootfs-overlay"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.15"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_MINIKUBE_PATH)/board/coreos/minikube/linux_defconfig"
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y

View File

@ -6,7 +6,7 @@
define AUTOMOUNT_INSTALL_INIT_SYSTEMD
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/automount/minikube-automount.service \
$(AUTOMOUNT_PKGDIR)/minikube-automount.service \
$(TARGET_DIR)/usr/lib/systemd/system/minikube-automount.service
ln -fs /usr/lib/systemd/system/minikube-automount.service \
@ -15,7 +15,7 @@ endef
define AUTOMOUNT_INSTALL_TARGET_CMDS
$(INSTALL) -Dm755 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/automount/minikube-automount \
$(AUTOMOUNT_PKGDIR)/minikube-automount \
$(TARGET_DIR)/usr/sbin/minikube-automount
endef

View File

@ -11,6 +11,7 @@ CONTAINERD_BIN_DEPENDENCIES = host-go libgpgme
CONTAINERD_BIN_GOPATH = $(@D)/_output
CONTAINERD_BIN_ENV = \
CGO_ENABLED=1 \
GO111MODULE=off \
GOPATH="$(CONTAINERD_BIN_GOPATH)" \
GOBIN="$(CONTAINERD_BIN_GOPATH)/bin" \
PATH=$(CONTAINERD_BIN_GOPATH)/bin:$(BR_PATH)
@ -42,13 +43,13 @@ define CONTAINERD_BIN_INSTALL_TARGET_CMDS
$(@D)/bin/ctr \
$(TARGET_DIR)/usr/bin
$(INSTALL) -Dm644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/containerd-bin/config.toml \
$(CONTAINERD_BIN_PKGDIR)/config.toml \
$(TARGET_DIR)/etc/containerd/config.toml
endef
define CONTAINERD_BIN_INSTALL_INIT_SYSTEMD
$(INSTALL) -Dm755 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/containerd-bin/containerd.service \
$(CONTAINERD_BIN_PKGDIR)/containerd.service \
$(TARGET_DIR)/usr/lib/systemd/system/containerd.service
$(call link-service,containerd.service)
$(call link-service,containerd-shutdown.service)

View File

@ -26,7 +26,7 @@ define CRIO_BIN_CONFIGURE_CMDS
mkdir -p $(CRIO_BIN_GOPATH)/src/github.com/cri-o
ln -sf $(@D) $(CRIO_BIN_GOPATH)/src/github.com/cri-o/cri-o
# Copy pre-generated conmon/config.h - see <https://github.com/cri-o/cri-o/issues/2575>
cp $(BR2_EXTERNAL_MINIKUBE_PATH)/package/crio-bin/conmon-config.h $(@D)/conmon/config.h
cp $(CRIO_BIN_PKGDIR)/conmon-config.h $(@D)/conmon/config.h
endef
define CRIO_BIN_BUILD_CMDS
@ -48,13 +48,13 @@ define CRIO_BIN_INSTALL_TARGET_CMDS
$(@D)/bin/pause \
$(TARGET_DIR)/usr/libexec/crio/pause
$(INSTALL) -Dm644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/crio-bin/crio.conf \
$(CRIO_BIN_PKGDIR)/crio.conf \
$(TARGET_DIR)/etc/crio/crio.conf
$(INSTALL) -Dm644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/crio-bin/policy.json \
$(CRIO_BIN_PKGDIR)/policy.json \
$(TARGET_DIR)/etc/containers/policy.json
$(INSTALL) -Dm644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/crio-bin/registries.conf \
$(CRIO_BIN_PKGDIR)/registries.conf \
$(TARGET_DIR)/etc/containers/registries.conf
mkdir -p $(TARGET_DIR)/etc/sysconfig
@ -64,7 +64,7 @@ endef
define CRIO_BIN_INSTALL_INIT_SYSTEMD
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) install.systemd DESTDIR=$(TARGET_DIR) PREFIX=$(TARGET_DIR)/usr
$(INSTALL) -Dm644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/crio-bin/crio.service \
$(CRIO_BIN_PKGDIR)/crio.service \
$(TARGET_DIR)/usr/lib/systemd/system/crio.service
$(call link-service,crio.service)
$(call link-service,crio-shutdown.service)

View File

@ -27,6 +27,10 @@ define DOCKER_BIN_INSTALL_TARGET_CMDS
$(@D)/dockerd \
$(TARGET_DIR)/bin/dockerd
$(INSTALL) -D -m 0755 \
$(@D)/docker-init \
$(TARGET_DIR)/bin/docker-init
$(INSTALL) -D -m 0755 \
$(@D)/docker-proxy \
$(TARGET_DIR)/bin/docker-proxy
@ -38,7 +42,7 @@ define DOCKER_BIN_INSTALL_INIT_SYSTEMD
$(TARGET_DIR)/usr/lib/systemd/system/docker.socket
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/docker-bin/forward.conf \
$(DOCKER_BIN_PKGDIR)/forward.conf \
$(TARGET_DIR)/etc/sysctl.d/forward.conf
endef

View File

@ -5,7 +5,10 @@
################################################################################
GLUSTER_VERSION = 4.1.5
GLUSTER_SITE = https://download.gluster.org/pub/gluster/glusterfs/4.1/$(GLUSTER_VERSION)
# Official gluster site has SSL problems
# https://bugzilla.redhat.com/show_bug.cgi?id=1572944
# GLUSTER_SITE = https://download.gluster.org/pub/gluster/glusterfs/4.1/$(GLUSTER_VERSION)
GLUSTER_SITE = http://download.openpkg.org/components/cache/glusterfs
GLUSTER_SOURCE = glusterfs-$(GLUSTER_VERSION).tar.gz
GLUSTER_CONF_OPTS = --disable-tiering --disable-ec-dynamic --disable-xmltest --disable-crypt-xlator --disable-georeplication --disable-ibverbs --disable-glupy --disable-gnfs --disable-cmocka --without-server
GLUSTER_INSTALL_TARGET_OPTS = DESTDIR=$(TARGET_DIR) install

View File

@ -4,8 +4,8 @@
#
################################################################################
HYPERV_DAEMONS_VERSION = 4.15.1
HYPERV_DAEMONS_SITE = https://www.kernel.org/pub/linux/kernel/v${HYPERV_DAEMONS_VERSION%%.*}.x
HYPERV_DAEMONS_VERSION = 4.19.76
HYPERV_DAEMONS_SITE = https://www.kernel.org/pub/linux/kernel/v4.x
HYPERV_DAEMONS_SOURCE = linux-$(HYPERV_DAEMONS_VERSION).tar.xz
define HYPERV_DAEMONS_BUILD_CMDS
@ -37,23 +37,23 @@ endef
define HYPERV_DAEMONS_INSTALL_INIT_SYSTEMD
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/70-hv_fcopy.rules \
$(HYPERV_DAEMONS_PKGDIR)/70-hv_fcopy.rules \
$(TARGET_DIR)/etc/udev/rules.d/70-hv_fcopy.rules
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/70-hv_kvp.rules \
$(HYPERV_DAEMONS_PKGDIR)/70-hv_kvp.rules \
$(TARGET_DIR)/etc/udev/rules.d/70-hv_kvp.rules
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/70-hv_vss.rules \
$(HYPERV_DAEMONS_PKGDIR)/70-hv_vss.rules \
$(TARGET_DIR)/etc/udev/rules.d/70-hv_vss.rules
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/hv_fcopy_daemon.service \
$(HYPERV_DAEMONS_PKGDIR)/hv_fcopy_daemon.service \
$(TARGET_DIR)/usr/lib/systemd/system/hv_fcopy_daemon.service
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/hv_kvp_daemon.service \
$(HYPERV_DAEMONS_PKGDIR)/hv_kvp_daemon.service \
$(TARGET_DIR)/usr/lib/systemd/system/hv_kvp_daemon.service
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/hyperv-daemons/hv_vss_daemon.service \
$(HYPERV_DAEMONS_PKGDIR)/hv_vss_daemon.service \
$(TARGET_DIR)/usr/lib/systemd/system/hv_vss_daemon.service
ln -fs /usr/lib/systemd/system/hv_fcopy_daemon.service \

View File

@ -1,3 +1,6 @@
# From http://download.virtualbox.org/virtualbox/5.1.30/SHA256SUMS
sha256 96cab2296fb014ce0a16b7b9603b52208b9403c10c1524b44201d3c274e8a821 VirtualBox-5.1.38.tar.bz2
sha256 0e7ee2c78ebf7cd0d3a933d51148bef04a64f64fb27ccf70d59cddf9ca1e517a VBoxGuestAdditions_5.1.38.iso
# From http://download.virtualbox.org/virtualbox/5.2.32/SHA256SUMS
sha256 ff6390e50cb03718cd3f5779627910999c12279b465e340c80d7175778a33958 VirtualBox-5.2.32.tar.bz2
sha256 4311c7408a3410e6a33264a9062347d9eec04f58339a49f0a60488c0cabc8996 VBoxGuestAdditions_5.2.32.iso

View File

@ -4,7 +4,7 @@
#
################################################################################
VBOX_GUEST_VERSION = 5.1.38
VBOX_GUEST_VERSION = 5.2.32
VBOX_GUEST_SITE = http://download.virtualbox.org/virtualbox/$(VBOX_GUEST_VERSION)
VBOX_GUEST_LICENSE = GPLv2
VBOX_GUEST_LICENSE_FILES = COPYING
@ -12,7 +12,7 @@ VBOX_GUEST_SOURCE = VirtualBox-$(VBOX_GUEST_VERSION).tar.bz2
VBOX_GUEST_EXTRA_DOWNLOADS = http://download.virtualbox.org/virtualbox/${VBOX_GUEST_VERSION}/VBoxGuestAdditions_${VBOX_GUEST_VERSION}.iso
define VBOX_GUEST_EXPORT_MODULES
( cd $(@D)/src/VBox/Additions/linux; ./export_modules modules.tar.gz )
( cd $(@D)/src/VBox/Additions/linux; ./export_modules.sh modules.tar.gz )
mkdir -p $(@D)/vbox-modules
tar -C $(@D)/vbox-modules -xzf $(@D)/src/VBox/Additions/linux/modules.tar.gz
endef
@ -20,7 +20,7 @@ endef
VBOX_GUEST_POST_EXTRACT_HOOKS += VBOX_GUEST_EXPORT_MODULES
VBOX_GUEST_MODULE_SUBDIRS = vbox-modules/
VBOX_GUEST_MODULE_MAKE_OPTS = KVERSION=$(LINUX_VERSION_PROBED)
VBOX_GUEST_MODULE_MAKE_OPTS = KVERSION=$(LINUX_VERSION_PROBED) KERN_DIR=$(LINUX_DIR)
define VBOX_GUEST_USERS
- -1 vboxsf -1 - - - - -
@ -28,7 +28,7 @@ endef
define VBOX_GUEST_INSTALL_INIT_SYSTEMD
$(INSTALL) -D -m 644 \
$(BR2_EXTERNAL_MINIKUBE_PATH)/package/vbox-guest/vboxservice.service \
$(VBOX_GUEST_PKGDIR)/vboxservice.service \
$(TARGET_DIR)/usr/lib/systemd/system/vboxservice.service
ln -fs /usr/lib/systemd/system/vboxservice.service \

View File

@ -48,7 +48,7 @@ func getSHAFromURL(url string) (string, error) {
}
func TestReleasesJson(t *testing.T) {
releases, err := notify.GetAllVersionsFromURL(constants.GithubMinikubeReleasesURL)
releases, err := notify.GetAllVersionsFromURL(notify.GithubMinikubeReleasesURL)
if err != nil {
t.Fatalf("Error getting releases.json: %v", err)
}

View File

@ -1,4 +1,28 @@
[
{
"name": "v1.5.2",
"checksums": {
"darwin": "734306019f837a6aee9cb7a0245839f98ea7688ee2cde387099334cb9356c2c4",
"linux": "1972a9a96de85e480012f6d2c9b8a88fd29217b99b1a973ed5e199386659f7e9",
"windows": "9f012922fd8d701070ef3951b0df77b720805a204d4d0dfa15d11899fda8a2d0"
}
},
{
"name": "v1.5.1",
"checksums": {
"darwin": "7ba345034e176566930d873acd0f38366dd14fdafd038febe600ea38c24c4208",
"linux": "5aed23a876770c92d0162fcf7862d855dc306516614be78ac6fbc47b5cba55e6",
"windows": "5a7bd914b0ae57e0853d72a06b7fb72e645417f2f3cd86d0f1bc4f636a04d160"
}
},
{
"name": "v1.5.0",
"checksums": {
"darwin": "eb716c176f404bb555966ff3947d5d9c5fb63eb902d11c83839fda492ff4b1fc",
"linux": "ca50dcc7c83d4dde484d650a5a1934ea1bef692340af3aa831d34c6e847b2770",
"windows": "bdd61e446f49570428848ad15337264edfecc55d1dd4aed4499d559f9c8383b9"
}
},
{
"name": "v1.4.0",
"checksums": {

13
enhancements/README.md Normal file
View File

@ -0,0 +1,13 @@
# Enhancements
The *minikube enhancement process (MEP)* is a way to propose, communicate, and coordinate on new efforts for the minikube project. You can read the full details in the [MEP proposal](implemented/20190925-minikube-enhancement-process/README.md)
MEP is based on a simplification of the [Kubernetes Enhancement Process](https://github.com/kubernetes/enhancements/blob/master/keps/0001-kubernetes-enhancement-proposal-process.md).
## Workflow
1. Copy `template.md` to `proposed/<date>-title/README.md`. Include supporting documents in the `proposed/<date>-title/` directory.
1. Send PR out for review, titled: `MEP: <title>`
1. Proposal will be discussed at the bi-weekly minikube office hours
1. After a 2-week review window, the proposal can be merged once there are 3 approving maintainers or reviewers. To keep proposals neutral, each reviewer must be independent and/or represent a different company.
1. In your PR that implements the enhancement, move the proposal to the `implemented/` folder.

View File

@ -0,0 +1,78 @@
# minikube enhancement process
First proposed: 2019-09-25
Authors: tstromberg
## Reviewer Priorities
Please review this proposal with the following priorities:
* Does this fit with minikube's principles?
* Are there other approaches to consider?
* Could the implementation be made simpler?
Please leave the above text in your proposal as instructions to the reader.
## Summary
A design review process for non-trivial enhancements to minikube.
## Goals
* Facilitate communication about the "how" and "why" of an enhancement before code is written
* Lightweight enough to not deter casual contributions
* A process applicable to any roadmap-worthy enhancement
## Non-Goals
* Coverage for smaller enhancements that would not be represented within the minikube roadmap.
* Reduced development velocity
## Design Details
The *minikube enhancement process (MEP)* is a way to propose, communicate, and coordinate on new efforts for the minikube project. MEP is based on a simplification of the [Kubernetes Enhancement Process](https://github.com/kubernetes/enhancements/blob/master/keps/0001-kubernetes-enhancement-proposal-process.md).
### Proposal Workflow
1. Copy `template.md` to `proposed/<date>-title.md`
1. Send PR out for review, titled: `Proposal: <title>`
1. Proposal will be discussed at the bi-weekly minikube office hours
1. After a 2-week review window, the proposal can be merged once there are 3 approving maintainers or reviewers. To keep proposals neutral, each reviewer must be independent and/or represent a different company.
### Implementation Workflow
1. In your PR that implements the enhancement, move the proposal to the `implemented/` folder.
## Alternatives Considered
### Kubernetes Enhancement Process
KEP's are a well-understood, but lengthier process geared toward making changes where multiple Kubernetes SIG's are affected.
#### Pro's
* Easily facilitate input from multiple SIG's
* Clear, well understood process within Kubernetes, shared by multiple projects
#### Con's
* Invisible to casual contributors to a project, as these proposals do not show up within the GitHub project page
* Lengthy template (1870+ words) that prompts for information that is not relevant to minikube
* Time commitment deters casual contribution
### Google Docs Proposal Template
Rather than maintaining Markdown documents in the minikube repository, we could use a Google Docs template, and then a Google Sheet to track proposal status.
### Pro's
* Easier editing for trivial proposals
### Con's
* Authors may waste unnecessary time styling output
* Styling may be inconsistent between proposals
* Invisible to casual contributors to a project, as these proposals do not show up within the GitHub project page

41
enhancements/template.md Normal file
View File

@ -0,0 +1,41 @@
# Your inspiring proposal title
* First proposed: <date>
* Authors: $full_name (@github-handle), $full_name2 (@github_handle2)
## 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
_(1 paragraph) What are you proposing, and why is it important to users and/or developers?_
## Goals
* _A bulleted list of specific goals for this proposal_
* _How will we know that this proposal has succeeded?_
## Non-Goals
* _A bulleted list of what is out of scope for this proposal_
* _Listing non-goals helps to focus the discussion_
## Design Details
_(2+ paragraphs) A short overview of your implementation idea, containing only as much detail as required to convey your idea._
_If you have multiple ideas, list them concisely._
_Include a testing plan to ensure that your enhancement is not broken by future changes._
## Alternatives Considered
_Alternative ideas that you are leaning against._

11
go.mod
View File

@ -21,14 +21,16 @@ require (
github.com/docker/machine v0.7.1-0.20190718054102-a555e4f7a8f5 // version is 0.7.1 to pin to a555e4f7a8f5
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/google/btree v1.0.0 // indirect
github.com/google/go-cmp v0.3.0
github.com/google/go-github/v25 v25.0.2
github.com/gorilla/mux v1.7.1 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.5.0 // indirect
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect
github.com/hashicorp/go-getter v1.3.0
github.com/hashicorp/go-getter v1.4.0
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604 // indirect
github.com/hashicorp/go-retryablehttp v0.5.4
github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect
@ -44,12 +46,14 @@ require (
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect
github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d // indirect
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/libvirt/libvirt-go v3.4.0+incompatible
github.com/machine-drivers/docker-machine-driver-vmware v0.1.1
github.com/mattn/go-isatty v0.0.8
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
github.com/moby/hyperkit v0.0.0-20171020124204-a12cd7250bcd
github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd
github.com/otiai10/copy v1.0.2
github.com/pborman/uuid v1.2.0
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/browser v0.0.0-20160118053552-9302be274faa
@ -69,13 +73,13 @@ require (
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
golang.org/x/text v0.3.2
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
gotest.tools v2.2.0+incompatible
k8s.io/api v0.0.0
k8s.io/apimachinery v0.0.0
k8s.io/client-go v0.0.0
@ -86,6 +90,7 @@ require (
replace (
git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
github.com/docker/machine => github.com/machine-drivers/machine v0.7.1-0.20190910053320-21bd2f51b8ea
github.com/hashicorp/go-getter => github.com/afbjorklund/go-getter v1.4.1-0.20190910175809-eb9f6c26742c
k8s.io/api => k8s.io/kubernetes/staging/src/k8s.io/api v0.0.0-20190623232353-8c3b7d7679cc
k8s.io/apiextensions-apiserver => k8s.io/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20190623232353-8c3b7d7679cc
k8s.io/apimachinery => k8s.io/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20190623232353-8c3b7d7679cc

83
go.sum
View File

@ -4,6 +4,13 @@ cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8=
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
@ -35,6 +42,8 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUW
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/afbjorklund/go-getter v1.4.1-0.20190910175809-eb9f6c26742c h1:18gEt7qzn7CW7qMkfPTFyyotlPbvPQo9o4IDV8jZqP4=
github.com/afbjorklund/go-getter v1.4.1-0.20190910175809-eb9f6c26742c/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@ -179,13 +188,18 @@ github.com/golang/mock v0.0.0-20160127222235-bd3c8e81be01/go.mod h1:oTYuIxOrZwtP
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/cadvisor v0.33.2-0.20190411163913-9db8c7dee20a/go.mod h1:1nql6U13uTHaLYB8rLS5x9IJc2qT6Xd/Tr1sTX6NE48=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -195,8 +209,6 @@ github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e h1:Hm0
github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v25 v25.0.2 h1:MqXE7nOlIF91NJ/PXAcvS2dC+XXCDbY7RvJzjyEPAoU=
github.com/google/go-github/v25 v25.0.2/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@ -205,6 +217,7 @@ github.com/google/gofuzz v1.0.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/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/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -212,6 +225,9 @@ github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3 h1:siORttZ36U2R/WjiJuDz8znElWBiAlO9rVt+mqJt0Cc=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
@ -233,6 +249,7 @@ github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6K
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-getter v1.3.0 h1:pFMSFlI9l5NaeuzkpE3L7BYk9qQ9juTAgXW/H0cqxcU=
github.com/hashicorp/go-getter v1.3.0/go.mod h1:/O1k/AizTN0QmfEKknCYGvICeyKUDqCYA8vvWtGWDeQ=
github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604 h1:VIq8E7fMiC4h3agg0ya56L0jHn7QisZZcWZXVKJb9jQ=
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
@ -243,6 +260,8 @@ github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PF
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v0.0.0-20160711231752-d8c773c4cba1/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@ -296,6 +315,8 @@ github.com/juju/version v0.0.0-20180108022336-b64dbd566305 h1:lQxPJ1URr2fjsKnJRt
github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U=
github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -383,6 +404,12 @@ github.com/opencontainers/runc v0.0.0-20181113202123-f000fe11ece1/go.mod h1:qT5X
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v0.0.0-20170621221121-4a2974bf1ee9/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@ -513,6 +540,9 @@ github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097 h1:Ucx5I1l1+TWXvqFm
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097/go.mod h1:lFZSWRIpCfE/pt91hHBBpV6+x87YlCjsp+aIR2qCPPU=
go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@ -525,15 +555,21 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -545,15 +581,24 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -572,6 +617,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -584,13 +633,23 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20170824195420-5d2fd3ccab98/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
@ -599,12 +658,18 @@ google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@ -612,11 +677,22 @@ google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 h1:mBVYJnbrXLA/ZCBTCe7PtEgAUP+1bg92qTaFoPHdz+8=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
@ -648,7 +724,9 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM=
k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
@ -693,6 +771,7 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/sig-storage-lib-external-provisioner v4.0.0+incompatible h1:qV3eFdgCp7Cp/ORjkJI9VBBEOntT+z385jLqdBtmgHA=
sigs.k8s.io/sig-storage-lib-external-provisioner v4.0.0+incompatible/go.mod h1:qhqLyNwJC49PoUalmtzYb4s9fT8HOMBTLbTY1QoVOqI=

1
hack/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
release-notes

View File

@ -0,0 +1,164 @@
/*
Copyright 2019 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 (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strings"
)
var (
boilerplatedir = flag.String("boilerplate-dir", ".", "Boilerplate directory for boilerplate files")
rootdir = flag.String("rootdir", "../../", "Root directory to examine")
verbose = flag.Bool("v", false, "Verbose")
skippedPaths = regexp.MustCompile(`Godeps|third_party|_gopath|_output|\.git|cluster/env.sh|vendor|test/e2e/generated/bindata.go|site/themes/docsy`)
windowdNewLine = regexp.MustCompile(`\r`)
txtExtension = regexp.MustCompile(`\.txt`)
goBuildTag = regexp.MustCompile(`(?m)^(// \+build.*\n)+\n`)
shebang = regexp.MustCompile(`(?m)^(#!.*\n)\n*`)
copyright = regexp.MustCompile(`Copyright YEAR`)
copyrightReal = regexp.MustCompile(`Copyright \d{4}`)
)
func main() {
flag.Parse()
refs, err := extensionToBoilerplate(*boilerplatedir)
if err != nil {
log.Fatal(err)
}
if len(refs) == 0 {
log.Fatal("no references in ", *boilerplatedir)
}
files, err := filesToCheck(*rootdir, refs)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
pass, err := filePasses(file, refs[filepath.Ext(file)])
if err != nil {
log.Println(err)
}
if !pass {
path, err := filepath.Abs(file)
if err != nil {
log.Println(err)
}
fmt.Println(path)
}
}
}
// extensionToBoilerplate returns a map of file extension to required boilerplate text.
func extensionToBoilerplate(dir string) (map[string][]byte, error) {
refs := make(map[string][]byte)
files, _ := filepath.Glob(dir + "/*.txt")
for _, filename := range files {
extension := strings.ToLower(filepath.Ext(txtExtension.ReplaceAllString(filename, "")))
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
refs[extension] = windowdNewLine.ReplaceAll(data, nil)
}
if *verbose {
dir, err := filepath.Abs(dir)
if err != nil {
return refs, err
}
fmt.Printf("Found %v boilerplates in %v for the following extensions:", len(refs), dir)
for ext := range refs {
fmt.Printf(" %v", ext)
}
fmt.Println()
}
return refs, nil
}
// filePasses checks whether the processed file is valid. Returning false means that the file does not the proper boilerplate template.
func filePasses(filename string, expectedBoilerplate []byte) (bool, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return false, err
}
data = windowdNewLine.ReplaceAll(data, nil)
extension := filepath.Ext(filename)
// remove build tags from the top of Go files
if extension == ".go" {
data = goBuildTag.ReplaceAll(data, nil)
}
// remove shebang from the top of shell files
if extension == ".sh" {
data = shebang.ReplaceAll(data, nil)
}
// if our test file is smaller than the reference it surely fails!
if len(data) < len(expectedBoilerplate) {
return false, nil
}
data = data[:len(expectedBoilerplate)]
// Search for "Copyright YEAR" which exists in the boilerplate, but shouldn't in the real thing
if copyright.Match(data) {
return false, nil
}
// Replace all occurrences of the regex "Copyright \d{4}" with "Copyright YEAR"
data = copyrightReal.ReplaceAll(data, []byte(`Copyright YEAR`))
return bytes.Equal(data, expectedBoilerplate), nil
}
// filesToCheck returns the list of the filers that will be checked for the boilerplate.
func filesToCheck(rootDir string, extensions map[string][]byte) ([]string, error) {
var outFiles []string
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
// remove current workdir from the beginig of the path in case it matches the skipped path
cwd, _ := os.Getwd()
// replace "\" with "\\" for windows style path
re := regexp.MustCompile(`\\`)
re = regexp.MustCompile(`^` + re.ReplaceAllString(cwd, `\\`))
if !info.IsDir() && !skippedPaths.MatchString(re.ReplaceAllString(filepath.Dir(path), "")) {
if extensions[strings.ToLower(filepath.Ext(path))] != nil {
outFiles = append(outFiles, path)
}
}
return nil
})
if err != nil {
return nil, err
}
if *verbose {
rootDir, err = filepath.Abs(rootDir)
if err != nil {
return outFiles, err
}
fmt.Printf("Found %v files to check in %v\n\n", len(outFiles), rootDir)
}
return outFiles, nil
}

View File

@ -1,170 +0,0 @@
#!/usr/bin/env python
# Copyright 2015 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.
from __future__ import print_function
import argparse
import glob
import json
import mmap
import os
import re
import sys
parser = argparse.ArgumentParser()
parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*')
rootdir = os.path.dirname(__file__) + "/../../"
rootdir = os.path.abspath(rootdir)
parser.add_argument("--rootdir", default=rootdir, help="root directory to examine")
default_boilerplate_dir = os.path.join(rootdir, "hack/boilerplate")
parser.add_argument("--boilerplate-dir", default=default_boilerplate_dir)
args = parser.parse_args()
def get_refs():
refs = {}
for path in glob.glob(os.path.join(args.boilerplate_dir, "boilerplate.*.txt")):
extension = os.path.basename(path).split(".")[1]
ref_file = open(path, 'r')
ref = ref_file.read().splitlines()
ref_file.close()
refs[extension] = ref
return refs
def file_passes(filename, refs, regexs):
try:
f = open(filename, 'r')
except:
return False
data = f.read()
f.close()
basename = os.path.basename(filename)
extension = file_extension(filename)
if extension != "":
ref = refs[extension]
else:
ref = refs[basename]
# remove build tags from the top of Go files
if extension == "go":
p = regexs["go_build_constraints"]
(data, found) = p.subn("", data, 1)
# remove shebang from the top of shell files
if extension == "sh":
p = regexs["shebang"]
(data, found) = p.subn("", data, 1)
data = data.splitlines()
# if our test file is smaller than the reference it surely fails!
if len(ref) > len(data):
return False
# trim our file to the same number of lines as the reference file
data = data[:len(ref)]
p = regexs["year"]
for d in data:
if p.search(d):
return False
# Replace all occurrences of the regex "2018|2017|2016|2015|2014" with "YEAR"
p = regexs["date"]
for i, d in enumerate(data):
(data[i], found) = p.subn('YEAR', d)
if found != 0:
break
# if we don't match the reference at this point, fail
if ref != data:
return False
return True
def file_extension(filename):
return os.path.splitext(filename)[1].split(".")[-1].lower()
skipped_dirs = ['Godeps', 'third_party', '_gopath', '_output', '.git', 'cluster/env.sh', "vendor", "test/e2e/generated/bindata.go"]
def normalize_files(files):
newfiles = []
for pathname in files:
if any(x in pathname for x in skipped_dirs):
continue
newfiles.append(pathname)
for i, pathname in enumerate(newfiles):
if not os.path.isabs(pathname):
newfiles[i] = os.path.join(rootdir, pathname)
return newfiles
def get_files(extensions):
files = []
if len(args.filenames) > 0:
files = args.filenames
else:
for root, dirs, walkfiles in os.walk(args.rootdir):
# don't visit certain dirs. This is just a performance improvement
# as we would prune these later in normalize_files(). But doing it
# cuts down the amount of filesystem walking we do and cuts down
# the size of the file list
for d in skipped_dirs:
if d in dirs:
dirs.remove(d)
for name in walkfiles:
pathname = os.path.join(root, name)
files.append(pathname)
files = normalize_files(files)
outfiles = []
for pathname in files:
basename = os.path.basename(pathname)
extension = file_extension(pathname)
if extension in extensions or basename in extensions:
outfiles.append(pathname)
return outfiles
def get_regexs():
regexs = {}
# Search for "YEAR" which exists in the boilerplate, but shouldn't in the real thing
regexs["year"] = re.compile( 'YEAR' )
# dates can be 2010 to 2039
regexs["date"] = re.compile( '(20[123]\d)' )
# strip // +build \n\n build constraints
regexs["go_build_constraints"] = re.compile(r"^(// \+build.*\n)+\n", re.MULTILINE)
# strip #!.* from shell scripts
regexs["shebang"] = re.compile(r"^(#!.*\n)\n*", re.MULTILINE)
return regexs
def main():
regexs = get_regexs()
refs = get_refs()
filenames = get_files(refs.keys())
for filename in filenames:
if not file_passes(filename, refs, regexs):
print(filename, file=sys.stdout)
if __name__ == "__main__":
sys.exit(main())

View File

@ -21,7 +21,9 @@ function prepend() {
local pattern=$1
local ref=$2
local headers=$3
local files=$(hack/boilerplate/boilerplate.py --rootdir ${ROOT_DIR} | grep -v "$ignore" | grep "$pattern")
pushd hack/boilerplate > /dev/null
local files=$(go run boilerplate.go -rootdir ${ROOT_DIR} -boilerplate-dir ${ROOT_DIR}/hack/boilerplate | grep -v "$ignore" | grep "$pattern")
popd > /dev/null
for f in ${files}; do
echo ${f};
local copyright="$(cat hack/boilerplate/boilerplate.${ref}.txt | sed s/YEAR/$(date +%Y)/g)"

View File

@ -23,8 +23,6 @@
# EXTRA_START_ARGS: additional flags to pass into minikube start
# EXTRA_ARGS: additional flags to pass into minikube
# JOB_NAME: the name of the logfile and check name to update on github
# PARALLEL_COUNT: number of tests to run in parallel
readonly TEST_ROOT="${HOME}/minikube-integration"
readonly TEST_HOME="${TEST_ROOT}/${OS_ARCH}-${VM_DRIVER}-${MINIKUBE_LOCATION}-$$-${COMMIT}"
@ -37,6 +35,7 @@ echo "job: ${JOB_NAME}"
echo "test home: ${TEST_HOME}"
echo "sudo: ${SUDO_PREFIX}"
echo "kernel: $(uname -v)"
echo "uptime: $(uptime)"
# Setting KUBECONFIG prevents the version ceck from erroring out due to permission issues
echo "kubectl: $(env KUBECONFIG=${TEST_HOME} kubectl version --client --short=true)"
echo "docker: $(docker version --format '{{ .Client.Version }}')"
@ -82,6 +81,7 @@ gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/gvisor-addon" testdata/
export MINIKUBE_BIN="out/minikube-${OS_ARCH}"
export E2E_BIN="out/e2e-${OS_ARCH}"
chmod +x "${MINIKUBE_BIN}" "${E2E_BIN}" out/docker-machine-driver-*
"${MINIKUBE_BIN}" version
procs=$(pgrep "minikube-${OS_ARCH}|e2e-${OS_ARCH}" || true)
if [[ "${procs}" != "" ]]; then
@ -91,28 +91,36 @@ if [[ "${procs}" != "" ]]; then
kill -9 ${procs} || true
fi
# Quickly notice misconfigured test roots
mkdir -p "${TEST_ROOT}"
# Cleanup stale test outputs.
echo ""
echo ">> Cleaning up after previous test runs ..."
for entry in $(ls ${TEST_ROOT}); do
test_path="${TEST_ROOT}/${entry}"
ls -lad "${test_path}" || continue
for stale_dir in ${TEST_ROOT}/*; do
echo "* Cleaning stale test root: ${stale_dir}"
for tunnel in $(find ${stale_dir} -name tunnels.json -type f); do
echo "* Cleaning stale test path: ${test_path}"
for tunnel in $(find ${test_path} -name tunnels.json -type f); do
env MINIKUBE_HOME="$(dirname ${tunnel})" ${MINIKUBE_BIN} tunnel --cleanup || true
done
for home in $(find ${stale_dir} -name .minikube -type d); do
env MINIKUBE_HOME="$(dirname ${home})" ${MINIKUBE_BIN} delete || true
sudo rm -Rf "${home}"
for home in $(find ${test_path} -name .minikube -type d); do
env MINIKUBE_HOME="$(dirname ${home})" ${MINIKUBE_BIN} delete --all || true
sudo rm -Rf "${home}"
done
for kconfig in $(find ${stale_dir} -name kubeconfig -type f); do
for kconfig in $(find ${test_path} -name kubeconfig -type f); do
sudo rm -f "${kconfig}"
done
rm -f "${stale_dir}/*" || true
rmdir "${stale_dir}" || ls "${stale_dir}"
# Be very specific to avoid accidentally deleting other items, like wildcards or devices
if [[ -d "${test_path}" ]]; then
rm -Rf "${test_path}" || true
elif [[ -f "${test_path}" ]]; then
rm -f "${test_path}" || true
fi
done
# sometimes tests left over zombie procs that won't exit
@ -134,14 +142,25 @@ if type -P virsh; then
fi
if type -P vboxmanage; then
vboxmanage list vms || true
vboxmanage list vms \
| egrep -o '{.*?}' \
| xargs -I {} sh -c "vboxmanage startvm {} --type emergencystop; vboxmanage unregistervm {} --delete" \
|| true
killall VBoxHeadless || true
sleep 1
killall -9 VBoxHeadless || true
for guid in $(vboxmanage list vms | grep -Eo '\{[a-zA-Z0-9-]+\}'); do
echo "- Removing stale VirtualBox VM: $guid"
vboxmanage startvm "${guid}" --type emergencystop || true
vboxmanage unregistervm "${guid}" || true
done
ifaces=$(vboxmanage list hostonlyifs | grep -E "^Name:" | awk '{ print $2 }')
for if in $ifaces; do
vboxmanage hostonlyif remove "${if}" || true
done
echo ">> VirtualBox VM list after clean up (should be empty):"
vboxmanage list vms || true
echo ">> VirtualBox interface list after clean up (should be empty):"
vboxmanage list hostonlyifs || true
fi
@ -213,22 +232,42 @@ mkdir -p "${TEST_HOME}"
export MINIKUBE_HOME="${TEST_HOME}/.minikube"
export KUBECONFIG="${TEST_HOME}/kubeconfig"
# Build the gvisor image. This will be copied into minikube and loaded by ctr.
# Used by TestContainerd for Gvisor Test.
# TODO: move this to integration test setup.
# Build the gvisor image so that we can integration test changes to pkg/gvisor
chmod +x ./testdata/gvisor-addon
# skipping gvisor mac because ofg https://github.com/kubernetes/minikube/issues/5137
if [ "$(uname)" != "Darwin" ]; then
docker build -t gcr.io/k8s-minikube/gvisor-addon:latest -f testdata/gvisor-addon-Dockerfile ./testdata
# Should match GVISOR_IMAGE_VERSION in Makefile
docker build -t gcr.io/k8s-minikube/gvisor-addon:2 -f testdata/gvisor-addon-Dockerfile ./testdata
fi
readonly LOAD=$(uptime | egrep -o "load average.*: [0-9]+" | cut -d" " -f3)
if [[ "${LOAD}" -gt 2 ]]; then
echo ""
echo "********************** LOAD WARNING ********************************"
echo "Load average is very high (${LOAD}), which may cause failures. Top:"
if [[ "$(uname)" == "Darwin" ]]; then
# Two samples, macOS does not calculate CPU usage on the first one
top -l 2 -o cpu -n 5 | tail -n 15
else
top -b -n1 | head -n 15
fi
echo "********************** LOAD WARNING ********************************"
echo "Sleeping 30s to see if load goes down ...."
sleep 30
uptime
fi
echo ""
echo ">> Starting ${E2E_BIN} at $(date)"
set -x
${SUDO_PREFIX}${E2E_BIN} \
-minikube-start-args="--vm-driver=${VM_DRIVER} ${EXTRA_START_ARGS}" \
-test.timeout=60m \
-test.parallel=${PARALLEL_COUNT} \
-expected-default-driver="${EXPECTED_DEFAULT_DRIVER}" \
-test.timeout=70m \
${EXTRA_TEST_ARGS} \
-binary="${MINIKUBE_BIN}" && result=$? || result=$?
set +x
echo ">> ${E2E_BIN} exited with ${result} at $(date)"
echo ""

View File

@ -19,21 +19,29 @@ set -uf -o pipefail
PATH=/usr/local/bin:/sbin:/usr/local/sbin:$PATH
exit_if_jenkins() {
jenkins=$(pgrep java)
if [[ "$jenkins" -- "" ]]; then
echo "no java, no jenkins"
return 0
# cleanup shared between Linux and macOS
function check_jenkins() {
jenkins_pid="$(pidof java)"
if [[ "${jenkins_pid}" = "" ]]; then
return
fi
pstree $jenkins | grep -v java && echo "jenkins is running..." && exit 1
pstree "${jenkins_pid}" \
| egrep -i 'bash|integration|e2e|minikube' \
&& echo "tests are is running on pid ${jenkins_pid} ..." \
&& exit 1
}
exit_if_jenkins
echo "waiting to see if any jobs are coming in..."
sleep 15
exit_if_jenkins
echo "doing it"
check_jenkins
logger "cleanup_and_reboot running - may shutdown in 60 seconds"
echo "cleanup_and_reboot running - may shutdown in 60 seconds" | wall
sleep 10
check_jenkins
logger "cleanup_and_reboot is happening!"
# kill jenkins to avoid an incoming request
killall java
sudo rm -Rf ~jenkins/.minikube || echo "could not delete minikube"
sudo rm -Rf ~/jenkins/minikube-integration/* || true
# macOS specific cleanup
sudo rm /var/db/dhcpd_leases || echo "could not clear dhcpd leases"
sudo softwareupdate -i -a -R
sudo reboot

View File

@ -0,0 +1,48 @@
#!/bin/bash
# Copyright 2019 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.
# cleanup shared between Linux and macOS
function check_jenkins() {
jenkins_pid="$(pidof java)"
if [[ "${jenkins_pid}" = "" ]]; then
return
fi
pstree "${jenkins_pid}" \
| egrep -i 'bash|integration|e2e|minikube' \
&& echo "tests are is running on pid ${jenkins_pid} ..." \
&& exit 1
}
check_jenkins
logger "cleanup_and_reboot running - may shutdown in 60 seconds"
echo "cleanup_and_reboot running - may shutdown in 60 seconds" | wall
sleep 10
check_jenkins
logger "cleanup_and_reboot is happening!"
# kill jenkins to avoid an incoming request
killall java
# Linux-specific cleanup
# disable localkube, kubelet
systemctl list-unit-files --state=enabled \
| grep kube \
| awk '{ print $1 }' \
| xargs systemctl disable
# update and reboot
apt update -y && apt upgrade -y && reboot

View File

@ -28,7 +28,7 @@ INSTALL_PATH=${2}
# installs or updates golang if right version doesn't exists
function check_and_install_golang() {
if ! go version &>/dev/null; then
echo "WARNING: No golang installation found in your enviroment."
echo "WARNING: No golang installation found in your environment."
install_golang "$VERSION_TO_INSTALL" "$INSTALL_PATH"
return
fi

View File

@ -28,7 +28,13 @@ set -e
OS_ARCH="linux-amd64"
VM_DRIVER="kvm2"
JOB_NAME="KVM_Linux"
PARALLEL_COUNT=4
EXPECTED_DEFAULT_DRIVER="kvm2"
# We pick kvm as our gvisor testbed because it is fast & reliable
EXTRA_TEST_ARGS="-gvisor"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP"
# Download files and set permissions
source ./common.sh

View File

@ -30,15 +30,16 @@ OS_ARCH="linux-amd64"
VM_DRIVER="none"
JOB_NAME="none_Linux"
EXTRA_ARGS="--bootstrapper=kubeadm"
PARALLEL_COUNT=1
EXPECTED_DEFAULT_DRIVER="kvm2"
SUDO_PREFIX="sudo -E "
export KUBECONFIG="/root/.kube/config"
# "none" driver specific cleanup from previous runs.
sudo kubeadm reset -f || true
# kubeadm reset may not stop pods immediately
docker rm -f $(docker ps -aq) >/dev/null 2>&1 || true
# Try without -f first, primarily because older kubeadm versions (v1.10) don't support it anyways.
sudo kubeadm reset || sudo kubeadm reset -f || true
# Cleanup data directory
sudo rm -rf /data/*
# Cleanup old Kubernetes configs
@ -50,5 +51,8 @@ systemctl is-active --quiet kubelet \
&& echo "stopping kubelet" \
&& sudo systemctl stop kubelet
mkdir -p cron && gsutil -m rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP"
# Download files and set permissions
source ./common.sh

View File

@ -28,7 +28,11 @@ set -e
OS_ARCH="linux-amd64"
VM_DRIVER="virtualbox"
JOB_NAME="VirtualBox_Linux"
PARALLEL_COUNT=4
EXPECTED_DEFAULT_DRIVER="kvm2"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP"
# Download files and set permissions
source ./common.sh

View File

@ -41,6 +41,8 @@ docker kill $(docker ps -q) || true
docker rm $(docker ps -aq) || true
make -j 16 all && failed=$? || failed=$?
"out/minikube-$(go env GOOS)-$(go env GOARCH)" version
gsutil cp "gs://${bucket}/logs/index.html" \
"gs://${bucket}/logs/${ghprbPullId}/index.html"
@ -58,9 +60,16 @@ if [[ "${rebuild}" -eq 1 ]]; then
make release-iso
fi
cp -r test/integration/testdata out/
# Don't upload the buildroot artifacts if they exist
rm -r out/buildroot || true
gsutil -m cp -r out/* "gs://${bucket}/${ghprbPullId}/"
# At this point, the out directory contains the jenkins scripts (populated by jenkins),
# testdata, and our build output. Push the changes to GCS so that worker nodes can re-use them.
# -d: delete remote files that don't exist (removed test files, for instance)
# -J: gzip compression
# -R: recursive. strangely, this is not the default for sync.
gsutil -m rsync -dJR out "gs://${bucket}/${ghprbPullId}"

View File

@ -31,7 +31,13 @@ VM_DRIVER="hyperkit"
JOB_NAME="HyperKit_macOS"
EXTRA_ARGS="--bootstrapper=kubeadm"
EXTRA_START_ARGS=""
PARALLEL_COUNT=3
EXPECTED_DEFAULT_DRIVER="hyperkit"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
install cron/cleanup_and_reboot_Darwin.sh $HOME/cleanup_and_reboot.sh || echo "FAILED TO INSTALL CLEANUP"
echo "*/30 * * * * $HOME/cleanup_and_reboot.sh" | crontab
crontab -l
# Download files and set permissions
source common.sh

View File

@ -29,7 +29,15 @@ OS_ARCH="darwin-amd64"
VM_DRIVER="virtualbox"
JOB_NAME="VirtualBox_macOS"
EXTRA_ARGS="--bootstrapper=kubeadm"
PARALLEL_COUNT=3
# hyperkit behaves better, so it has higher precedence.
# Assumes that hyperkit is also installed on the VirtualBox CI host.
EXPECTED_DEFAULT_DRIVER="hyperkit"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
install cron/cleanup_and_reboot_Darwin.sh $HOME/cleanup_and_reboot.sh || echo "FAILED TO GET INSTALL CLEANUP"
echo "*/30 * * * * $HOME/cleanup_and_reboot.sh" | crontab
crontab -l
# Download files and set permissions
source common.sh

View File

@ -39,6 +39,12 @@ if [ -z "${NEW_SHA256}" ]; then
exit 1
fi
echo "***********************************************************************"
echo "Sorry, this script has not yet been updated to support non-cask updates"
echo "See https://github.com/kubernetes/minikube/issues/5779"
echo "***********************************************************************"
exit 99
git config --global user.name "${GITHUB_USER}"
git config --global user.email "${GITHUB_USER}@google.com"

View File

@ -19,7 +19,7 @@ gsutil.cmd -m cp -r gs://minikube-builds/$env:MINIKUBE_LOCATION/testdata .
./out/minikube-windows-amd64.exe delete
out/e2e-windows-amd64.exe -minikube-start-args="--vm-driver=hyperv --hyperv-virtual-switch=primary-virtual-switch" -binary=out/minikube-windows-amd64.exe -test.v -test.timeout=65m
out/e2e-windows-amd64.exe --expected-default-driver=hyperv -minikube-start-args="--vm-driver=hyperv --hyperv-virtual-switch=primary-virtual-switch" -binary=out/minikube-windows-amd64.exe -test.v -test.timeout=65m
$env:result=$lastexitcode
# If the last exit code was 0->success, x>0->error
If($env:result -eq 0){$env:status="success"}

View File

@ -19,7 +19,7 @@ gsutil.cmd -m cp -r gs://minikube-builds/$env:MINIKUBE_LOCATION/testdata .
./out/minikube-windows-amd64.exe delete
out/e2e-windows-amd64.exe -minikube-start-args="--vm-driver=virtualbox" -binary=out/minikube-windows-amd64.exe -test.v -test.timeout=30m
out/e2e-windows-amd64.exe -minikube-start-args="--vm-driver=virtualbox" -expected-default-driver=hyperv -binary=out/minikube-windows-amd64.exe -test.v -test.timeout=30m
$env:result=$lastexitcode
# If the last exit code was 0->success, x>0->error
If($env:result -eq 0){$env:status="success"}

View File

@ -18,7 +18,23 @@ set -eux -o pipefail
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
go run "${DIR}/release_notes/listpullreqs.go"
install_release_notes_helper() {
release_notes_workdir="$(mktemp -d)"
trap 'rm -rf -- ${release_notes_workdir}' RETURN
# See https://stackoverflow.com/questions/56842385/using-go-get-to-download-binaries-without-adding-them-to-go-mod for this workaround
cd "${release_notes_workdir}"
go mod init release-notes
GOBIN="$DIR" go get github.com/corneliusweig/release-notes
cd -
}
if ! [[ -x "${DIR}/release-notes" ]]; then
echo >&2 'Installing release-notes'
install_release_notes_helper
fi
"${DIR}/release-notes" kubernetes minikube
echo "Huge thank you for this release towards our contributors: "
git log "$(git describe --abbrev=0)".. --format="%aN" --reverse | sort | uniq | awk '{printf "- %s\n", $0 }'

Some files were not shown because too many files have changed in this diff Show More