Merge master
commit
62a452edab
|
@ -5,7 +5,7 @@ env:
|
|||
- GOPROXY=https://proxy.golang.org
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.12.7
|
||||
- go: 1.12.9
|
||||
- language: python
|
||||
before_install: pip install flake8
|
||||
script: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
|
|
14
Makefile
14
Makefile
|
@ -22,6 +22,9 @@ ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).0
|
|||
VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
|
||||
DEB_VERSION ?= $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
|
||||
RPM_VERSION ?= $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
|
||||
# used by hack/jenkins/release_build_and_upload.sh and KVM_BUILD_IMAGE, see also BUILD_IMAGE below
|
||||
GO_VERSION ?= 1.12.9
|
||||
|
||||
INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1)
|
||||
BUILDROOT_BRANCH ?= 2018.05.3
|
||||
REGISTRY?=gcr.io/k8s-minikube
|
||||
|
@ -31,8 +34,8 @@ COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
|
|||
COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}")
|
||||
|
||||
HYPERKIT_BUILD_IMAGE ?= karalabe/xgo-1.12.x
|
||||
# NOTE: "latest" as of 2019-07-12. kube-cross images aren't updated as often as Kubernetes
|
||||
BUILD_IMAGE ?= k8s.gcr.io/kube-cross:v1.12.7-1
|
||||
# NOTE: "latest" as of 2019-08-15. kube-cross images aren't updated as often as Kubernetes
|
||||
BUILD_IMAGE ?= k8s.gcr.io/kube-cross:v$(GO_VERSION)-1
|
||||
ISO_BUILD_IMAGE ?= $(REGISTRY)/buildroot-image
|
||||
KVM_BUILD_IMAGE ?= $(REGISTRY)/kvm-build-image:$(GO_VERSION)
|
||||
|
||||
|
@ -44,10 +47,7 @@ MINIKUBE_UPLOAD_LOCATION := gs://${MINIKUBE_BUCKET}
|
|||
MINIKUBE_RELEASES_URL=https://github.com/kubernetes/minikube/releases/download
|
||||
|
||||
KERNEL_VERSION ?= 4.15
|
||||
|
||||
# Currently *only* used for the KVM_BUILD_IMAGE, see also BUILD_IMAGE above
|
||||
GO_VERSION ?= 1.12.7
|
||||
|
||||
# latest from https://github.com/golangci/golangci-lint/releases
|
||||
GOLINT_VERSION ?= v1.17.1
|
||||
# Limit number of default jobs, to avoid the CI builds running out of memory
|
||||
GOLINT_JOBS ?= 4
|
||||
|
@ -101,7 +101,7 @@ SOURCE_DIRS = $(CMD_SOURCE_DIRS) test
|
|||
SOURCE_PACKAGES = ./cmd/... ./pkg/... ./test/...
|
||||
|
||||
# kvm2 ldflags
|
||||
KVM2_LDFLAGS := -X k8s.io/minikube/pkg/drivers/kvm.version=$(VERSION) -X k8s.io/minikube/pkg/drivers/kvm.gitCommitID=$(COMMIT)
|
||||
KVM2_LDFLAGS := -X k8s.io/minikube/pkg/drivers/kvm.version=$(VERSION) -X k8s.io/minikube/pkg/drivers/kvm.gitCommitID=$(COMMIT)
|
||||
|
||||
# hyperkit ldflags
|
||||
HYPERKIT_LDFLAGS := -X k8s.io/minikube/pkg/drivers/hyperkit.version=$(VERSION) -X k8s.io/minikube/pkg/drivers/hyperkit.gitCommitID=$(COMMIT)
|
||||
|
|
|
@ -55,7 +55,7 @@ minikube is a Kubernetes [#sig-cluster-lifecycle](https://github.com/kubernetes/
|
|||
* [**#minikube on Kubernetes Slack**](https://kubernetes.slack.com) - Live chat with minikube developers!
|
||||
* [minikube-users mailing list](https://groups.google.com/forum/#!forum/minikube-users)
|
||||
* [minikube-dev mailing list](https://groups.google.com/forum/#!forum/minikube-dev)
|
||||
* [Bi-weekly office hours, Mondays @ 10am PST](https://tinyurl.com/minikube-oh)
|
||||
* [Bi-weekly office hours, Mondays @ 11am PST](https://tinyurl.com/minikube-oh)
|
||||
|
||||
* [Contributing](https://minikube.sigs.k8s.io/docs/contributing/)
|
||||
* [Development Roadmap](https://minikube.sigs.k8s.io/docs/contributing/roadmap/)
|
||||
|
|
|
@ -67,7 +67,7 @@ var deleteCacheCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
func imagesInConfigFile() ([]string, error) {
|
||||
configFile, err := config.ReadConfig()
|
||||
configFile, err := config.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -290,7 +290,7 @@ func configurableFields() string {
|
|||
|
||||
// ListConfigMap list entries from config file
|
||||
func ListConfigMap(name string) ([]string, error) {
|
||||
configFile, err := config.ReadConfig()
|
||||
configFile, err := config.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ func AddToConfigMap(name string, images []string) error {
|
|||
return err
|
||||
}
|
||||
// Set the values
|
||||
cfg, err := config.ReadConfig()
|
||||
cfg, err := config.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ func DeleteFromConfigMap(name string, images []string) error {
|
|||
return err
|
||||
}
|
||||
// Set the values
|
||||
cfg, err := config.ReadConfig()
|
||||
cfg, err := config.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func Set(name string, value string) error {
|
|||
}
|
||||
|
||||
// Set the value
|
||||
config, err := pkgConfig.ReadConfig()
|
||||
config, err := pkgConfig.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func init() {
|
|||
|
||||
// Unset unsets a property
|
||||
func Unset(name string) error {
|
||||
m, err := pkgConfig.ReadConfig()
|
||||
m, err := pkgConfig.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -55,7 +55,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()
|
||||
cfg, err := config.ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func runDelete(cmd *cobra.Command, args []string) {
|
|||
|
||||
cc, err := pkg_config.Load()
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
out.ErrT(out.Sad, "Error loading profile config: {{.error}}", out.V{"name": profile})
|
||||
out.ErrT(out.Sad, "Error loading profile {{.name}}: {{.error}}", out.V{"name": profile, "error": err})
|
||||
}
|
||||
|
||||
// In the case of "none", we want to uninstall Kubernetes as there is no VM to delete
|
||||
|
@ -71,27 +71,38 @@ func runDelete(cmd *cobra.Command, args []string) {
|
|||
uninstallKubernetes(api, cc.KubernetesConfig, viper.GetString(cmdcfg.Bootstrapper))
|
||||
}
|
||||
|
||||
if err := killMountProcess(); err != nil {
|
||||
out.T(out.FailureType, "Failed to kill mount process: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
||||
if err = cluster.DeleteHost(api); err != nil {
|
||||
switch err := errors.Cause(err).(type) {
|
||||
switch errors.Cause(err).(type) {
|
||||
case mcnerror.ErrHostDoesNotExist:
|
||||
out.T(out.Meh, `"{{.name}}" cluster does not exist`, out.V{"name": profile})
|
||||
default:
|
||||
exit.WithError("Failed to delete cluster", err)
|
||||
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})
|
||||
}
|
||||
}
|
||||
|
||||
if err := killMountProcess(); err != nil {
|
||||
out.FatalT("Failed to kill mount process: {{.error}}", out.V{"error": err})
|
||||
// In case DeleteHost didn't complete the job.
|
||||
machineDir := filepath.Join(constants.GetMinipath(), "machines", profile)
|
||||
if _, err := os.Stat(machineDir); err == nil {
|
||||
out.T(out.DeletingHost, `Removing {{.directory}} ...`, out.V{"directory": machineDir})
|
||||
err := os.RemoveAll(machineDir)
|
||||
if err != nil {
|
||||
exit.WithError("Unable to remove machine directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := pkg_config.DeleteProfile(viper.GetString(pkg_config.MachineProfile)); err != nil {
|
||||
if err := pkg_config.DeleteProfile(profile); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
out.T(out.Meh, `"{{.profile_name}}" profile does not exist`, out.V{"profile_name": profile})
|
||||
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 "{{.cluster_name}}" cluster has been deleted.`, out.V{"cluster_name": profile})
|
||||
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 {
|
||||
|
|
|
@ -102,6 +102,7 @@ const (
|
|||
dnsProxy = "dns-proxy"
|
||||
hostDNSResolver = "host-dns-resolver"
|
||||
waitUntilHealthy = "wait"
|
||||
waitTimeout = "wait-timeout"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -111,7 +112,7 @@ var (
|
|||
insecureRegistry []string
|
||||
apiServerNames []string
|
||||
apiServerIPs []net.IP
|
||||
extraOptions pkgutil.ExtraOptionSlice
|
||||
extraOptions cfg.ExtraOptionSlice
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -148,6 +149,7 @@ func initMinikubeFlags() {
|
|||
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().Duration(waitTimeout, 3*time.Minute, "max time to wait per Kubernetes core services to be healthy.")
|
||||
}
|
||||
|
||||
// initKubernetesFlags inits the commandline flags for kubernetes related options
|
||||
|
@ -321,7 +323,7 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
// special ops for none driver, like change minikube directory.
|
||||
prepareNone(viper.GetString(vmDriver))
|
||||
if viper.GetBool(waitUntilHealthy) {
|
||||
if err := bs.WaitCluster(config.KubernetesConfig); err != nil {
|
||||
if err := bs.WaitCluster(config.KubernetesConfig, viper.GetDuration(waitTimeout)); err != nil {
|
||||
exit.WithError("Wait failed", err)
|
||||
}
|
||||
}
|
||||
|
@ -538,8 +540,8 @@ func validateConfig() {
|
|||
|
||||
// check that kubeadm extra args contain only whitelisted parameters
|
||||
for param := range extraOptions.AsMap().Get(kubeadm.Kubeadm) {
|
||||
if !pkgutil.ContainsString(kubeadm.KubeadmExtraArgsWhitelist[kubeadm.KubeadmCmdParam], param) &&
|
||||
!pkgutil.ContainsString(kubeadm.KubeadmExtraArgsWhitelist[kubeadm.KubeadmConfigParam], param) {
|
||||
if !cfg.ContainsParam(kubeadm.KubeadmExtraArgsWhitelist[kubeadm.KubeadmCmdParam], param) &&
|
||||
!cfg.ContainsParam(kubeadm.KubeadmExtraArgsWhitelist[kubeadm.KubeadmConfigParam], param) {
|
||||
exit.UsageT("Sorry, the kubeadm.{{.parameter_name}} parameter is currently not supported by --extra-config", out.V{"parameter_name": param})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
## storage-provisioner-gluster addon
|
||||
[Gluster](https://gluster.org/), a scalable network filesystem that provides dynamic provisioning of PersistenVolumeClaims.
|
||||
[Gluster](https://gluster.org/), a scalable network filesystem that provides dynamic provisioning of PersistentVolumeClaims.
|
||||
|
||||
### Starting Minikube
|
||||
This addon works within Minikube, without any additional configuration.
|
||||
|
|
|
@ -71,11 +71,12 @@ echo ">> Downloading test inputs from ${MINIKUBE_LOCATION} ..."
|
|||
gsutil -qm cp \
|
||||
"gs://minikube-builds/${MINIKUBE_LOCATION}/minikube-${OS_ARCH}" \
|
||||
"gs://minikube-builds/${MINIKUBE_LOCATION}/docker-machine-driver"-* \
|
||||
"gs://minikube-builds/${MINIKUBE_LOCATION}/e2e-${OS_ARCH}" \
|
||||
"gs://minikube-builds/${MINIKUBE_LOCATION}/gvisor-addon" out
|
||||
"gs://minikube-builds/${MINIKUBE_LOCATION}/e2e-${OS_ARCH}" out
|
||||
|
||||
gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/testdata"/* testdata/
|
||||
|
||||
gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/gvisor-addon" testdata/
|
||||
|
||||
|
||||
# Set the executable bit on the e2e binary and out binary
|
||||
export MINIKUBE_BIN="out/minikube-${OS_ARCH}"
|
||||
|
@ -125,6 +126,18 @@ for stale_dir in ${TEST_ROOT}/*; do
|
|||
rmdir "${stale_dir}" || true
|
||||
done
|
||||
|
||||
|
||||
# sometimes tests left over zombie procs that won't exit
|
||||
# for example:
|
||||
# jenkins 20041 0.0 0.0 0 0 ? Z Aug19 0:00 [minikube-linux-] <defunct>
|
||||
zombie_defuncts=$(ps -A -ostat,ppid | awk '/[zZ]/ && !a[$2]++ {print $2}')
|
||||
if [[ "${zombie_defuncts}" != "" ]]; then
|
||||
echo "Found zombie defunct procs to kill..."
|
||||
ps -f -p ${zombie_defuncts} || true
|
||||
sudo -E kill ${zombie_defuncts} || true
|
||||
fi
|
||||
|
||||
|
||||
if type -P virsh; then
|
||||
virsh -c qemu:///system list --all
|
||||
virsh -c qemu:///system list --all \
|
||||
|
@ -165,6 +178,7 @@ if type -P vboxmanage; then
|
|||
vboxmanage list vms || true
|
||||
fi
|
||||
|
||||
|
||||
if type -P hdiutil; then
|
||||
hdiutil info | grep -E "/dev/disk[1-9][^s]" || true
|
||||
hdiutil info \
|
||||
|
@ -198,6 +212,14 @@ if [[ "${VM_DRIVER}" == "hyperkit" ]]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
vboxprocs=$(pgrep VBox || true)
|
||||
if [[ "${vboxprocs}" != "" ]]; then
|
||||
echo "error: killing left over virtualbox processes ..."
|
||||
ps -f -p ${vboxprocs} || true
|
||||
sudo -E kill ${vboxprocs} || true
|
||||
fi
|
||||
|
||||
|
||||
kprocs=$(pgrep kubectl || true)
|
||||
if [[ "${kprocs}" != "" ]]; then
|
||||
echo "error: killing hung kubectl processes ..."
|
||||
|
@ -241,6 +263,16 @@ export MINIKUBE_HOME="${TEST_HOME}/.minikube"
|
|||
export MINIKUBE_WANTREPORTERRORPROMPT=False
|
||||
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.
|
||||
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
|
||||
fi
|
||||
|
||||
|
||||
# Display the default image URL
|
||||
echo ""
|
||||
echo ">> ISO URL"
|
||||
|
@ -274,9 +306,6 @@ ${SUDO_PREFIX} rm -f "${KUBECONFIG}" || true
|
|||
rmdir "${TEST_HOME}"
|
||||
echo ">> ${TEST_HOME} completed at $(date)"
|
||||
|
||||
# Build the gvisor image. This will be copied into minikube and loaded by ctr.
|
||||
docker build -t gcr.io/k8s-minikube/gvisor-addon:latest -f testdata/gvisor-addon-Dockerfile out
|
||||
|
||||
if [[ "${MINIKUBE_LOCATION}" != "master" ]]; then
|
||||
readonly target_url="https://storage.googleapis.com/minikube-builds/logs/${MINIKUBE_LOCATION}/${JOB_NAME}.txt"
|
||||
curl -s "https://api.github.com/repos/kubernetes/minikube/statuses/${COMMIT}?access_token=$access_token" \
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
if (($# < 2)); then
|
||||
echo "ERROR: given ! ($#) number of parameters but expect 2."
|
||||
echo "USAGE: ./check_and_install_golang.sh VERSION_TO_INSTALL INSTALL_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION_TO_INSTALL=${1}
|
||||
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."
|
||||
install_golang "$VERSION_TO_INSTALL" "$INSTALL_PATH"
|
||||
return
|
||||
fi
|
||||
|
||||
# golang has been installed and check its version
|
||||
if [[ $(go version) =~ (([0-9]+)\.([0-9]+).([0-9]+).([\.0-9]*)) ]]; then
|
||||
HOST_VERSION=${BASH_REMATCH[1]}
|
||||
if [ $HOST_VERSION = $VERSION_TO_INSTALL ]; then
|
||||
echo "go version on the host looks good : $HOST_VERSION"
|
||||
else
|
||||
echo "WARNING: expected go version to be $VERSION_TO_INSTALL but got $HOST_VERSION"
|
||||
install_golang "$VERSION_TO_INSTALL" "$INSTALL_PATH"
|
||||
fi
|
||||
else
|
||||
echo "ERROR: Failed to parse golang version: $HOST_VERSION"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
# install_golang takes two parameters version and path to install.
|
||||
function install_golang() {
|
||||
echo "Installing golang version: $1 on $2"
|
||||
pushd /tmp >/dev/null
|
||||
# using sudo because previously installed versions might have been installed by a different user.
|
||||
# as it was the case on jenkins VM.
|
||||
sudo curl -qL -O "https://storage.googleapis.com/golang/go${1}.linux-amd64.tar.gz" &&
|
||||
sudo tar xfa go${1}.linux-amd64.tar.gz &&
|
||||
sudo rm -rf "${2}/go" &&
|
||||
sudo mv go "${2}/" && sudo chown -R $(whoami): ${2}/go
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
check_and_install_golang
|
|
@ -25,6 +25,11 @@ set -eux -o pipefail
|
|||
|
||||
readonly bucket="minikube-builds"
|
||||
|
||||
# Make sure the right golang version is installed based on Makefile
|
||||
WANT_GOLANG_VERSION=$(grep '^GO_VERSION' Makefile | awk '{ print $3 }')
|
||||
./hack/jenkins/installers/check_install_golang.sh $WANT_GOLANG_VERSION /usr/local
|
||||
|
||||
|
||||
declare -rx BUILD_IN_DOCKER=y
|
||||
declare -rx GOPATH=/var/lib/jenkins/go
|
||||
declare -rx ISO_BUCKET="${bucket}/${ghprbPullId}"
|
||||
|
|
|
@ -31,6 +31,11 @@ export DEB_VERSION=${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}
|
|||
export RPM_VERSION=${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}
|
||||
export GOPATH=~/go
|
||||
|
||||
# Make sure the right golang version is installed based on Makefile
|
||||
WANT_GOLANG_VERSION=$(grep '^GO_VERSION' Makefile | awk '{ print $3 }')
|
||||
./hack/jenkins/installers/check_install_golang.sh $WANT_GOLANG_VERSION /usr/local
|
||||
|
||||
|
||||
# Make sure the tag matches the Makefile
|
||||
cat Makefile | grep "VERSION_MAJOR ?=" | grep $VERSION_MAJOR
|
||||
cat Makefile | grep "VERSION_MINOR ?=" | grep $VERSION_MINOR
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
package kapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -29,15 +29,13 @@ import (
|
|||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
watchtools "k8s.io/client-go/tools/watch"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kconst "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/minikube/pkg/minikube/proxy"
|
||||
)
|
||||
|
||||
|
@ -48,30 +46,8 @@ var (
|
|||
ReasonableStartTime = time.Minute * 5
|
||||
)
|
||||
|
||||
// PodStore stores pods
|
||||
type PodStore struct {
|
||||
cache.Store
|
||||
stopCh chan struct{}
|
||||
Reflector *cache.Reflector
|
||||
}
|
||||
|
||||
// List lists the pods
|
||||
func (s *PodStore) List() []*core.Pod {
|
||||
objects := s.Store.List()
|
||||
pods := make([]*core.Pod, 0)
|
||||
for _, o := range objects {
|
||||
pods = append(pods, o.(*core.Pod))
|
||||
}
|
||||
return pods
|
||||
}
|
||||
|
||||
// Stop stops the pods
|
||||
func (s *PodStore) Stop() {
|
||||
close(s.stopCh)
|
||||
}
|
||||
|
||||
// GetClient gets the client from config
|
||||
func GetClient(kubectlContext ...string) (kubernetes.Interface, error) {
|
||||
// Client gets the kubernetes client from default kubeconfig
|
||||
func Client(kubectlContext ...string) (kubernetes.Interface, error) {
|
||||
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
configOverrides := &clientcmd.ConfigOverrides{}
|
||||
if kubectlContext != nil {
|
||||
|
@ -92,50 +68,16 @@ func GetClient(kubectlContext ...string) (kubernetes.Interface, error) {
|
|||
return client, nil
|
||||
}
|
||||
|
||||
// NewPodStore creates a new PodStore
|
||||
func NewPodStore(c kubernetes.Interface, namespace string, label fmt.Stringer, field fmt.Stringer) *PodStore {
|
||||
lw := &cache.ListWatch{
|
||||
ListFunc: func(options meta.ListOptions) (runtime.Object, error) {
|
||||
options.LabelSelector = label.String()
|
||||
options.FieldSelector = field.String()
|
||||
obj, err := c.CoreV1().Pods(namespace).List(options)
|
||||
return runtime.Object(obj), err
|
||||
},
|
||||
WatchFunc: func(options meta.ListOptions) (watch.Interface, error) {
|
||||
options.LabelSelector = label.String()
|
||||
options.FieldSelector = field.String()
|
||||
return c.CoreV1().Pods(namespace).Watch(options)
|
||||
},
|
||||
}
|
||||
store := cache.NewStore(cache.MetaNamespaceKeyFunc)
|
||||
stopCh := make(chan struct{})
|
||||
reflector := cache.NewReflector(lw, &core.Pod{}, store, 0)
|
||||
go reflector.Run(stopCh)
|
||||
return &PodStore{Store: store, stopCh: stopCh, Reflector: reflector}
|
||||
}
|
||||
|
||||
// StartPods starts all pods
|
||||
func StartPods(c kubernetes.Interface, namespace string, pod core.Pod, waitForRunning bool) error {
|
||||
pod.ObjectMeta.Labels["name"] = pod.Name
|
||||
if waitForRunning {
|
||||
label := labels.SelectorFromSet(labels.Set(map[string]string{"name": pod.Name}))
|
||||
err := WaitForPodsWithLabelRunning(c, namespace, label)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error waiting for pod %s to be running: %v", pod.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForPodsWithLabelRunning waits for all matching pods to become Running and at least one matching pod exists.
|
||||
func WaitForPodsWithLabelRunning(c kubernetes.Interface, ns string, label labels.Selector) error {
|
||||
func WaitForPodsWithLabelRunning(c kubernetes.Interface, ns string, label labels.Selector, timeOut ...time.Duration) error {
|
||||
start := time.Now()
|
||||
glog.Infof("Waiting for pod with label %q in ns %q ...", ns, label)
|
||||
lastKnownPodNumber := -1
|
||||
return wait.PollImmediate(constants.APICallRetryInterval, ReasonableStartTime, func() (bool, error) {
|
||||
f := func() (bool, error) {
|
||||
listOpts := meta.ListOptions{LabelSelector: label.String()}
|
||||
pods, err := c.CoreV1().Pods(ns).List(listOpts)
|
||||
if err != nil {
|
||||
glog.Infof("error getting Pods with label selector %q [%v]\n", label.String(), err)
|
||||
glog.Infof("temporary error: getting Pods with label selector %q : [%v]\n", label.String(), err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
@ -150,45 +92,23 @@ func WaitForPodsWithLabelRunning(c kubernetes.Interface, ns string, label labels
|
|||
|
||||
for _, pod := range pods.Items {
|
||||
if pod.Status.Phase != core.PodRunning {
|
||||
glog.Infof("waiting for pod %q, current state: %s: [%v]\n", label.String(), pod.Status.Phase, err)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
t := ReasonableStartTime
|
||||
if timeOut != nil {
|
||||
t = timeOut[0]
|
||||
}
|
||||
err := wait.PollImmediate(kconst.APICallRetryInterval, t, f)
|
||||
glog.Infof("duration metric: took %s to wait for %s ...", time.Since(start), label)
|
||||
return err
|
||||
}
|
||||
|
||||
// WaitForPodDelete waits for a pod to be deleted
|
||||
func WaitForPodDelete(c kubernetes.Interface, ns string, label fmt.Stringer) error {
|
||||
return wait.PollImmediate(constants.APICallRetryInterval, ReasonableMutateTime, func() (bool, error) {
|
||||
listOpts := meta.ListOptions{LabelSelector: label.String()}
|
||||
pods, err := c.CoreV1().Pods(ns).List(listOpts)
|
||||
if err != nil {
|
||||
glog.Infof("error getting Pods with label selector %q [%v]\n", label.String(), err)
|
||||
return false, nil
|
||||
}
|
||||
return len(pods.Items) == 0, nil
|
||||
})
|
||||
}
|
||||
|
||||
// WaitForEvent waits for the given event to appear
|
||||
func WaitForEvent(c kubernetes.Interface, ns string, reason string) error {
|
||||
return wait.PollImmediate(constants.APICallRetryInterval, ReasonableMutateTime, func() (bool, error) {
|
||||
events, err := c.EventsV1beta1().Events("default").List(meta.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Infof("error getting events: %v", err)
|
||||
return false, nil
|
||||
}
|
||||
for _, e := range events.Items {
|
||||
if e.Reason == reason {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
// WaitForRCToStabilize waits till the RC has a matching generation/replica count between spec and status.
|
||||
// WaitForRCToStabilize waits till the RC has a matching generation/replica count between spec and status. used by integration tests
|
||||
func WaitForRCToStabilize(c kubernetes.Interface, ns, name string, timeout time.Duration) error {
|
||||
options := meta.ListOptions{FieldSelector: fields.Set{
|
||||
"metadata.name": name,
|
||||
|
@ -222,7 +142,7 @@ func WaitForRCToStabilize(c kubernetes.Interface, ns, name string, timeout time.
|
|||
return err
|
||||
}
|
||||
|
||||
// WaitForDeploymentToStabilize waits till the Deployment has a matching generation/replica count between spec and status.
|
||||
// WaitForDeploymentToStabilize waits till the Deployment has a matching generation/replica count between spec and status. used by integrationt tests
|
||||
func WaitForDeploymentToStabilize(c kubernetes.Interface, ns, name string, timeout time.Duration) error {
|
||||
options := meta.ListOptions{FieldSelector: fields.Set{
|
||||
"metadata.name": name,
|
||||
|
@ -281,32 +201,6 @@ func WaitForService(c kubernetes.Interface, namespace, name string, exist bool,
|
|||
return nil
|
||||
}
|
||||
|
||||
// WaitForServiceEndpointsNum waits until the amount of endpoints that implement service to expectNum.
|
||||
func WaitForServiceEndpointsNum(c kubernetes.Interface, namespace, serviceName string, expectNum int, interval, timeout time.Duration) error {
|
||||
return wait.Poll(interval, timeout, func() (bool, error) {
|
||||
glog.Infof("Waiting for amount of service:%s endpoints to be %d", serviceName, expectNum)
|
||||
list, err := c.CoreV1().Endpoints(namespace).List(meta.ListOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, e := range list.Items {
|
||||
if e.Name == serviceName && countEndpointsNum(&e) == expectNum {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
func countEndpointsNum(e *core.Endpoints) int {
|
||||
num := 0
|
||||
for _, sub := range e.Subsets {
|
||||
num += len(sub.Addresses)
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
// IsRetryableAPIError returns if this error is retryable or not
|
||||
func IsRetryableAPIError(err error) bool {
|
||||
return apierr.IsTimeout(err) || apierr.IsServerTimeout(err) || apierr.IsTooManyRequests(err) || apierr.IsInternalError(err)
|
|
@ -18,6 +18,7 @@ package bootstrapper
|
|||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
@ -39,7 +40,7 @@ type Bootstrapper interface {
|
|||
UpdateCluster(config.KubernetesConfig) error
|
||||
RestartCluster(config.KubernetesConfig) error
|
||||
DeleteCluster(config.KubernetesConfig) error
|
||||
WaitCluster(config.KubernetesConfig) error
|
||||
WaitCluster(config.KubernetesConfig, time.Duration) error
|
||||
// LogCommands returns a map of log type to a command which will display that log.
|
||||
LogCommands(LogOptions) map[string]string
|
||||
SetupCerts(cfg config.KubernetesConfig) error
|
||||
|
|
|
@ -35,6 +35,8 @@ import (
|
|||
"golang.org/x/sync/errgroup"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
kconst "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
|
@ -182,13 +184,13 @@ func (k *Bootstrapper) LogCommands(o bootstrapper.LogOptions) map[string]string
|
|||
}
|
||||
|
||||
// createFlagsFromExtraArgs converts kubeadm extra args into flags to be supplied from the commad linne
|
||||
func createFlagsFromExtraArgs(extraOptions util.ExtraOptionSlice) string {
|
||||
func createFlagsFromExtraArgs(extraOptions config.ExtraOptionSlice) string {
|
||||
kubeadmExtraOpts := extraOptions.AsMap().Get(Kubeadm)
|
||||
|
||||
// kubeadm allows only a small set of parameters to be supplied from the command line when the --config param
|
||||
// is specified, here we remove those that are not allowed
|
||||
for opt := range kubeadmExtraOpts {
|
||||
if !util.ContainsString(KubeadmExtraArgsWhitelist[KubeadmCmdParam], opt) {
|
||||
if !config.ContainsParam(KubeadmExtraArgsWhitelist[KubeadmCmdParam], opt) {
|
||||
// kubeadmExtraOpts is a copy so safe to delete
|
||||
delete(kubeadmExtraOpts, opt)
|
||||
}
|
||||
|
@ -198,7 +200,7 @@ func createFlagsFromExtraArgs(extraOptions util.ExtraOptionSlice) string {
|
|||
|
||||
// StartCluster starts the cluster
|
||||
func (k *Bootstrapper) StartCluster(k8s config.KubernetesConfig) error {
|
||||
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
|
||||
version, err := parseKubernetesVersion(k8s.KubernetesVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing kubernetes version")
|
||||
}
|
||||
|
@ -307,13 +309,13 @@ func addAddons(files *[]assets.CopyableFile, data interface{}) error {
|
|||
}
|
||||
|
||||
// WaitCluster blocks until Kubernetes appears to be healthy.
|
||||
func (k *Bootstrapper) WaitCluster(k8s config.KubernetesConfig) error {
|
||||
func (k *Bootstrapper) WaitCluster(k8s config.KubernetesConfig, timeout time.Duration) error {
|
||||
// Do not wait for "k8s-app" pods in the case of CNI, as they are managed
|
||||
// by a CNI plugin which is usually started after minikube has been brought
|
||||
// up. Otherwise, minikube won't start, as "k8s-app" pods are not ready.
|
||||
componentsOnly := k8s.NetworkPlugin == "cni"
|
||||
out.T(out.WaitingPods, "Waiting for:")
|
||||
client, err := util.GetClient()
|
||||
client, err := kapi.Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "k8s client")
|
||||
}
|
||||
|
@ -326,13 +328,12 @@ func (k *Bootstrapper) WaitCluster(k8s config.KubernetesConfig) error {
|
|||
}
|
||||
|
||||
for _, p := range PodsByLayer {
|
||||
if componentsOnly && p.key != "component" {
|
||||
if componentsOnly && p.key != "component" { // skip component check if network plugin is cni
|
||||
continue
|
||||
}
|
||||
|
||||
out.String(" %s", p.name)
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{p.key: p.value}))
|
||||
if err := util.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", selector, timeout); err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("waiting for %s=%s", p.key, p.value))
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +343,7 @@ func (k *Bootstrapper) WaitCluster(k8s config.KubernetesConfig) error {
|
|||
|
||||
// RestartCluster restarts the Kubernetes cluster configured by kubeadm
|
||||
func (k *Bootstrapper) RestartCluster(k8s config.KubernetesConfig) error {
|
||||
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
|
||||
version, err := parseKubernetesVersion(k8s.KubernetesVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing kubernetes version")
|
||||
}
|
||||
|
@ -398,8 +399,9 @@ func (k *Bootstrapper) waitForAPIServer(k8s config.KubernetesConfig) error {
|
|||
return fmt.Errorf("apiserver process never appeared")
|
||||
}
|
||||
|
||||
glog.Infof("Waiting for apiserver status ...")
|
||||
return wait.PollImmediate(time.Millisecond*300, time.Minute*1, func() (bool, error) {
|
||||
start := time.Now()
|
||||
glog.Infof("Waiting for apiserver ...")
|
||||
f := func() (bool, error) {
|
||||
status, err := k.GetAPIServerStatus(net.ParseIP(k8s.NodeIP), k8s.NodePort)
|
||||
glog.Infof("apiserver status: %s, err: %v", status, err)
|
||||
if err != nil {
|
||||
|
@ -409,7 +411,10 @@ func (k *Bootstrapper) waitForAPIServer(k8s config.KubernetesConfig) error {
|
|||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
err = wait.PollImmediate(kconst.APICallRetryInterval, kconst.DefaultControlPlaneTimeout, f)
|
||||
glog.Infof("duration metric: took %s to wait for apiserver status ...", time.Since(start))
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCluster removes the components that were started earlier
|
||||
|
@ -425,7 +430,7 @@ func (k *Bootstrapper) DeleteCluster(k8s config.KubernetesConfig) error {
|
|||
|
||||
// PullImages downloads images that will be used by RestartCluster
|
||||
func (k *Bootstrapper) PullImages(k8s config.KubernetesConfig) error {
|
||||
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
|
||||
version, err := parseKubernetesVersion(k8s.KubernetesVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing kubernetes version")
|
||||
}
|
||||
|
@ -448,7 +453,7 @@ func (k *Bootstrapper) SetupCerts(k8s config.KubernetesConfig) error {
|
|||
// NewKubeletConfig generates a new systemd unit containing a configured kubelet
|
||||
// based on the options present in the KubernetesConfig.
|
||||
func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte, error) {
|
||||
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
|
||||
version, err := parseKubernetesVersion(k8s.KubernetesVersion)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing kubernetes version")
|
||||
}
|
||||
|
@ -551,7 +556,7 @@ func (k *Bootstrapper) UpdateCluster(cfg config.KubernetesConfig) error {
|
|||
}
|
||||
|
||||
// createExtraComponentConfig generates a map of component to extra args for all of the components except kubeadm
|
||||
func createExtraComponentConfig(extraOptions util.ExtraOptionSlice, version semver.Version, componentFeatureArgs string) ([]ComponentExtraArgs, error) {
|
||||
func createExtraComponentConfig(extraOptions config.ExtraOptionSlice, version semver.Version, componentFeatureArgs string) ([]ComponentExtraArgs, error) {
|
||||
extraArgsSlice, err := NewComponentExtraArgs(extraOptions, version, componentFeatureArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -571,7 +576,7 @@ func createExtraComponentConfig(extraOptions util.ExtraOptionSlice, version semv
|
|||
|
||||
// generateConfig generates the kubeadm.yaml file
|
||||
func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte, error) {
|
||||
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
|
||||
version, err := parseKubernetesVersion(k8s.KubernetesVersion)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing kubernetes version")
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
func TestGenerateKubeletConfig(t *testing.T) {
|
||||
|
@ -145,29 +144,29 @@ ExecStart=/var/lib/minikube/binaries/v1.15.2/kubelet --authorization-mode=Webhoo
|
|||
}
|
||||
}
|
||||
|
||||
func getExtraOpts() []util.ExtraOption {
|
||||
return util.ExtraOptionSlice{
|
||||
util.ExtraOption{
|
||||
func getExtraOpts() []config.ExtraOption {
|
||||
return config.ExtraOptionSlice{
|
||||
config.ExtraOption{
|
||||
Component: Apiserver,
|
||||
Key: "fail-no-swap",
|
||||
Value: "true",
|
||||
},
|
||||
util.ExtraOption{
|
||||
config.ExtraOption{
|
||||
Component: ControllerManager,
|
||||
Key: "kube-api-burst",
|
||||
Value: "32",
|
||||
},
|
||||
util.ExtraOption{
|
||||
config.ExtraOption{
|
||||
Component: Scheduler,
|
||||
Key: "scheduler-name",
|
||||
Value: "mini-scheduler",
|
||||
},
|
||||
util.ExtraOption{
|
||||
config.ExtraOption{
|
||||
Component: Kubeadm,
|
||||
Key: "ignore-preflight-errors",
|
||||
Value: "true",
|
||||
},
|
||||
util.ExtraOption{
|
||||
config.ExtraOption{
|
||||
Component: Kubeadm,
|
||||
Key: "dry-run",
|
||||
Value: "true",
|
||||
|
@ -175,9 +174,9 @@ func getExtraOpts() []util.ExtraOption {
|
|||
}
|
||||
}
|
||||
|
||||
func getExtraOptsPodCidr() []util.ExtraOption {
|
||||
return util.ExtraOptionSlice{
|
||||
util.ExtraOption{
|
||||
func getExtraOptsPodCidr() []config.ExtraOption {
|
||||
return config.ExtraOptionSlice{
|
||||
config.ExtraOption{
|
||||
Component: Kubeadm,
|
||||
Key: "pod-network-cidr",
|
||||
Value: "192.168.32.0/20",
|
||||
|
@ -229,7 +228,7 @@ func TestGenerateConfig(t *testing.T) {
|
|||
{"crio", "crio", false, config.KubernetesConfig{}},
|
||||
{"options", "docker", false, config.KubernetesConfig{ExtraOptions: extraOpts}},
|
||||
{"crio-options-gates", "crio", false, config.KubernetesConfig{ExtraOptions: extraOpts, FeatureGates: "a=b"}},
|
||||
{"unknown-component", "docker", true, config.KubernetesConfig{ExtraOptions: util.ExtraOptionSlice{util.ExtraOption{Component: "not-a-real-component", Key: "killswitch", Value: "true"}}}},
|
||||
{"unknown-component", "docker", true, config.KubernetesConfig{ExtraOptions: config.ExtraOptionSlice{config.ExtraOption{Component: "not-a-real-component", Key: "killswitch", Value: "true"}}}},
|
||||
{"containerd-api-port", "containerd", false, config.KubernetesConfig{NodePort: 12345}},
|
||||
{"containerd-pod-network-cidr", "containerd", false, config.KubernetesConfig{ExtraOptions: extraOptsPodCidr}},
|
||||
{"image-repository", "docker", false, config.KubernetesConfig{ImageRepository: "test/repo"}},
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
@ -43,7 +44,7 @@ const (
|
|||
|
||||
// ExtraConfigForComponent generates a map of flagname-value pairs for a k8s
|
||||
// component.
|
||||
func ExtraConfigForComponent(component string, opts util.ExtraOptionSlice, version semver.Version) (map[string]string, error) {
|
||||
func ExtraConfigForComponent(component string, opts config.ExtraOptionSlice, version semver.Version) (map[string]string, error) {
|
||||
versionedOpts, err := DefaultOptionsForComponentAndVersion(component, version)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "setting version specific options for %s", component)
|
||||
|
@ -78,7 +79,7 @@ var componentToKubeadmConfigKey = map[string]string{
|
|||
}
|
||||
|
||||
// NewComponentExtraArgs creates a new ComponentExtraArgs
|
||||
func NewComponentExtraArgs(opts util.ExtraOptionSlice, version semver.Version, featureGates string) ([]ComponentExtraArgs, error) {
|
||||
func NewComponentExtraArgs(opts config.ExtraOptionSlice, version semver.Version, featureGates string) ([]ComponentExtraArgs, error) {
|
||||
var kubeadmExtraArgs []ComponentExtraArgs
|
||||
for _, extraOpt := range opts {
|
||||
if _, ok := componentToKubeadmConfigKey[extraOpt.Component]; !ok {
|
||||
|
@ -158,8 +159,8 @@ func Supports(featureName string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ParseKubernetesVersion parses the kubernetes version
|
||||
func ParseKubernetesVersion(version string) (semver.Version, error) {
|
||||
// parseKubernetesVersion parses the kubernetes version
|
||||
func parseKubernetesVersion(version string) (semver.Version, error) {
|
||||
// Strip leading 'v' prefix from version for semver parsing
|
||||
v, err := semver.Make(version[1:])
|
||||
if err != nil {
|
||||
|
@ -182,45 +183,9 @@ func convertToFlags(opts map[string]string) string {
|
|||
return strings.Join(flags, " ")
|
||||
}
|
||||
|
||||
// VersionedExtraOption holds information on flags to apply to a specific range
|
||||
// of versions
|
||||
type VersionedExtraOption struct {
|
||||
// Special Cases:
|
||||
//
|
||||
// If LessThanOrEqual and GreaterThanOrEqual are both nil, the flag will be applied
|
||||
// to all versions
|
||||
//
|
||||
// If LessThanOrEqual == GreaterThanOrEqual, the flag will only be applied to that
|
||||
// specific version
|
||||
|
||||
// The flag and component that will be set
|
||||
Option util.ExtraOption
|
||||
|
||||
// This flag will only be applied to versions before or equal to this version
|
||||
// If it is the default value, it will have no upper bound on versions the
|
||||
// flag is applied to
|
||||
LessThanOrEqual semver.Version
|
||||
|
||||
// The flag will only be applied to versions after or equal to this version
|
||||
// If it is the default value, it will have no lower bound on versions the
|
||||
// flag is applied to
|
||||
GreaterThanOrEqual semver.Version
|
||||
}
|
||||
|
||||
// NewUnversionedOption returns a VersionedExtraOption that applies to all versions.
|
||||
func NewUnversionedOption(component, k, v string) VersionedExtraOption {
|
||||
return VersionedExtraOption{
|
||||
Option: util.ExtraOption{
|
||||
Component: component,
|
||||
Key: k,
|
||||
Value: v,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var versionSpecificOpts = []VersionedExtraOption{
|
||||
var versionSpecificOpts = []config.VersionedExtraOption{
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Kubelet,
|
||||
Key: "fail-swap-on",
|
||||
Value: "false",
|
||||
|
@ -228,22 +193,22 @@ var versionSpecificOpts = []VersionedExtraOption{
|
|||
GreaterThanOrEqual: semver.MustParse("1.8.0-alpha.0"),
|
||||
},
|
||||
// Kubeconfig args
|
||||
NewUnversionedOption(Kubelet, "kubeconfig", "/etc/kubernetes/kubelet.conf"),
|
||||
NewUnversionedOption(Kubelet, "bootstrap-kubeconfig", "/etc/kubernetes/bootstrap-kubelet.conf"),
|
||||
config.NewUnversionedOption(Kubelet, "kubeconfig", "/etc/kubernetes/kubelet.conf"),
|
||||
config.NewUnversionedOption(Kubelet, "bootstrap-kubeconfig", "/etc/kubernetes/bootstrap-kubelet.conf"),
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Kubelet,
|
||||
Key: "require-kubeconfig",
|
||||
Value: "true",
|
||||
},
|
||||
LessThanOrEqual: semver.MustParse("1.9.10"),
|
||||
},
|
||||
NewUnversionedOption(Kubelet, "hostname-override", constants.DefaultNodeName),
|
||||
config.NewUnversionedOption(Kubelet, "hostname-override", constants.DefaultNodeName),
|
||||
|
||||
// System pods args
|
||||
NewUnversionedOption(Kubelet, "pod-manifest-path", constants.GuestManifestsDir),
|
||||
config.NewUnversionedOption(Kubelet, "pod-manifest-path", constants.GuestManifestsDir),
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Kubelet,
|
||||
Key: "allow-privileged",
|
||||
Value: "true",
|
||||
|
@ -252,17 +217,17 @@ var versionSpecificOpts = []VersionedExtraOption{
|
|||
},
|
||||
|
||||
// Network args
|
||||
NewUnversionedOption(Kubelet, "cluster-dns", "10.96.0.10"),
|
||||
NewUnversionedOption(Kubelet, "cluster-domain", "cluster.local"),
|
||||
config.NewUnversionedOption(Kubelet, "cluster-dns", "10.96.0.10"),
|
||||
config.NewUnversionedOption(Kubelet, "cluster-domain", "cluster.local"),
|
||||
|
||||
// Auth args
|
||||
NewUnversionedOption(Kubelet, "authorization-mode", "Webhook"),
|
||||
NewUnversionedOption(Kubelet, "client-ca-file", path.Join(constants.GuestCertsDir, "ca.crt")),
|
||||
config.NewUnversionedOption(Kubelet, "authorization-mode", "Webhook"),
|
||||
config.NewUnversionedOption(Kubelet, "client-ca-file", path.Join(constants.GuestCertsDir, "ca.crt")),
|
||||
|
||||
// Cgroup args
|
||||
NewUnversionedOption(Kubelet, "cgroup-driver", "cgroupfs"),
|
||||
config.NewUnversionedOption(Kubelet, "cgroup-driver", "cgroupfs"),
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Apiserver,
|
||||
Key: "admission-control",
|
||||
Value: strings.Join(util.DefaultLegacyAdmissionControllers, ","),
|
||||
|
@ -271,7 +236,7 @@ var versionSpecificOpts = []VersionedExtraOption{
|
|||
GreaterThanOrEqual: semver.MustParse("1.9.0-alpha.0"),
|
||||
},
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Apiserver,
|
||||
Key: "enable-admission-plugins",
|
||||
Value: strings.Join(util.DefaultLegacyAdmissionControllers, ","),
|
||||
|
@ -280,7 +245,7 @@ var versionSpecificOpts = []VersionedExtraOption{
|
|||
LessThanOrEqual: semver.MustParse("1.13.1000"),
|
||||
},
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Apiserver,
|
||||
Key: "enable-admission-plugins",
|
||||
Value: strings.Join(util.DefaultV114AdmissionControllers, ","),
|
||||
|
@ -289,7 +254,7 @@ var versionSpecificOpts = []VersionedExtraOption{
|
|||
},
|
||||
|
||||
{
|
||||
Option: util.ExtraOption{
|
||||
Option: config.ExtraOption{
|
||||
Component: Kubelet,
|
||||
Key: "cadvisor-port",
|
||||
Value: "0",
|
||||
|
|
|
@ -94,7 +94,7 @@ func TestVersionIsBetween(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseKubernetesVersion(t *testing.T) {
|
||||
version, err := ParseKubernetesVersion("v1.8.0-alpha.5")
|
||||
version, err := parseKubernetesVersion("v1.8.0-alpha.5")
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing version: %v", err)
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ func configureHost(h *host.Host, e *engine.Options) error {
|
|||
if err != nil {
|
||||
return errors.Wrap(err, "detecting provisioner")
|
||||
}
|
||||
glog.Infof("Provisioning: %+v", *h.HostOptions)
|
||||
glog.Infof("Provisioning with %s: %+v", provisioner.String(), *h.HostOptions)
|
||||
if err := provisioner.Provision(*h.HostOptions.SwarmOptions, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions); err != nil {
|
||||
return errors.Wrap(err, "provision")
|
||||
}
|
||||
|
@ -338,6 +338,7 @@ func engineOptions(config cfg.MachineConfig) *engine.Options {
|
|||
InsecureRegistry: append([]string{pkgutil.DefaultServiceCIDR}, config.InsecureRegistry...),
|
||||
RegistryMirror: config.RegistryMirror,
|
||||
ArbitraryFlags: config.DockerOpt,
|
||||
InstallURL: drivers.DefaultEngineInstallURL,
|
||||
}
|
||||
return &o
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ type MinikubeConfig map[string]interface{}
|
|||
|
||||
// Get gets a named value from config
|
||||
func Get(name string) (string, error) {
|
||||
m, err := ReadConfig()
|
||||
m, err := ReadConfig(constants.ConfigFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -88,11 +88,7 @@ func WriteConfig(configFile string, m MinikubeConfig) error {
|
|||
}
|
||||
|
||||
// ReadConfig reads in the JSON minikube config
|
||||
func ReadConfig() (MinikubeConfig, error) {
|
||||
return readConfig(constants.ConfigFile)
|
||||
}
|
||||
|
||||
func readConfig(configFile string) (MinikubeConfig, error) {
|
||||
func ReadConfig(configFile string) (MinikubeConfig, error) {
|
||||
f, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
|
|
@ -104,9 +104,9 @@ func Test_get(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_readConfig(t *testing.T) {
|
||||
func TestReadConfig(t *testing.T) {
|
||||
// non existing file
|
||||
mkConfig, err := readConfig("non_existing_file")
|
||||
mkConfig, err := ReadConfig("non_existing_file")
|
||||
if err != nil {
|
||||
t.Fatalf("Error not exepected but got %v", err)
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ func Test_readConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
// invalid config file
|
||||
mkConfig, err = readConfig("./testdata/.minikube/config/invalid_config.json")
|
||||
mkConfig, err = ReadConfig("./testdata/.minikube/config/invalid_config.json")
|
||||
if err == nil {
|
||||
t.Fatalf("Error expected but got none")
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func Test_readConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
// valid config file
|
||||
mkConfig, err = readConfig("./testdata/.minikube/config/valid_config.json")
|
||||
mkConfig, err = ReadConfig("./testdata/.minikube/config/valid_config.json")
|
||||
if err != nil {
|
||||
t.Fatalf("Error not expected but got %v", err)
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ func TestWriteConfig(t *testing.T) {
|
|||
}
|
||||
defer os.Remove(configFile.Name())
|
||||
|
||||
mkConfig, err := readConfig(configFile.Name())
|
||||
mkConfig, err := ReadConfig(configFile.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("Error not expected but got %v", err)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
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.
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -76,7 +76,7 @@ func (es *ExtraOptionSlice) String() string {
|
|||
// component is not specified, all of the components are used.
|
||||
func (es *ExtraOptionSlice) Get(key string, component ...string) string {
|
||||
for _, opt := range *es {
|
||||
if component == nil || ContainsString(component, opt.Component) {
|
||||
if component == nil || ContainsParam(component, opt.Component) {
|
||||
if opt.Key == key {
|
||||
return opt.Value
|
||||
}
|
||||
|
@ -107,3 +107,25 @@ func (es *ExtraOptionSlice) Type() string {
|
|||
func (cm ComponentExtraOptionMap) Get(component string) map[string]string {
|
||||
return cm[component]
|
||||
}
|
||||
|
||||
// ContainsParam checks if a given slice of strings contains the provided string.
|
||||
// If a modifier func is provided, it is called with the slice item before the comparation.
|
||||
func ContainsParam(slice []string, s string) bool {
|
||||
for _, item := range slice {
|
||||
if item == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NewUnversionedOption returns a VersionedExtraOption that applies to all versions.
|
||||
func NewUnversionedOption(component, k, v string) VersionedExtraOption {
|
||||
return VersionedExtraOption{
|
||||
Option: ExtraOption{
|
||||
Component: component,
|
||||
Key: k,
|
||||
Value: v,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
package config
|
||||
|
||||
import (
|
||||
"flag"
|
|
@ -19,6 +19,7 @@ package config
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -82,8 +83,33 @@ type KubernetesConfig struct {
|
|||
FeatureGates string
|
||||
ServiceCIDR string
|
||||
ImageRepository string
|
||||
ExtraOptions util.ExtraOptionSlice
|
||||
ExtraOptions ExtraOptionSlice
|
||||
|
||||
ShouldLoadCachedImages bool
|
||||
EnableDefaultCNI bool
|
||||
}
|
||||
|
||||
// VersionedExtraOption holds information on flags to apply to a specific range
|
||||
// of versions
|
||||
type VersionedExtraOption struct {
|
||||
// Special Cases:
|
||||
//
|
||||
// If LessThanOrEqual and GreaterThanOrEqual are both nil, the flag will be applied
|
||||
// to all versions
|
||||
//
|
||||
// If LessThanOrEqual == GreaterThanOrEqual, the flag will only be applied to that
|
||||
// specific version
|
||||
|
||||
// The flag and component that will be set
|
||||
Option ExtraOption
|
||||
|
||||
// This flag will only be applied to versions before or equal to this version
|
||||
// If it is the default value, it will have no upper bound on versions the
|
||||
// flag is applied to
|
||||
LessThanOrEqual semver.Version
|
||||
|
||||
// The flag will only be applied to versions after or equal to this version
|
||||
// If it is the default value, it will have no lower bound on versions the
|
||||
// flag is applied to
|
||||
GreaterThanOrEqual semver.Version
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (r *Containerd) Enable(disOthers bool) error {
|
|||
if err := enableIPForwarding(r.Runner); err != nil {
|
||||
return err
|
||||
}
|
||||
// Oherwise, containerd will fail API requests with 'Unimplemented'
|
||||
// Otherwise, containerd will fail API requests with 'Unimplemented'
|
||||
return r.Runner.Run("sudo systemctl restart containerd")
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ func (api *LocalClient) NewHost(driverName string, rawDriver []byte) (*host.Host
|
|||
func (api *LocalClient) Load(name string) (*host.Host, error) {
|
||||
h, err := api.Filestore.Load(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "filestore")
|
||||
return nil, errors.Wrapf(err, "filestore %q", name)
|
||||
}
|
||||
|
||||
var def registry.DriverDef
|
||||
|
|
|
@ -36,8 +36,6 @@ import (
|
|||
"k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
const updateLinkPrefix = "https://github.com/kubernetes/minikube/releases/tag/v"
|
||||
|
||||
var (
|
||||
timeLayout = time.RFC1123
|
||||
lastUpdateCheckFilePath = constants.MakeMiniPath("last_update_check")
|
||||
|
@ -67,7 +65,7 @@ func MaybePrintUpdateText(url string, lastUpdatePath string) {
|
|||
if err := writeTimeToFile(lastUpdateCheckFilePath, time.Now().UTC()); err != nil {
|
||||
glog.Errorf("write time failed: %v", err)
|
||||
}
|
||||
url := fmt.Sprintf("%s/%s", updateLinkPrefix, latestVersion)
|
||||
url := "https://github.com/kubernetes/minikube/releases/tag/v" + latestVersion.String()
|
||||
out.ErrT(out.WarningType, `minikube {{.version}} is available! Download it: {{.url}}`, out.V{"version": latestVersion, "url": url})
|
||||
out.T(out.Tip, "To disable this notice, run: 'minikube config set WantUpdateNotification false'")
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ var (
|
|||
Translations map[string]interface{}
|
||||
)
|
||||
|
||||
// T translates the given string to the supplied language.
|
||||
// T translates the given string to the preferred language.
|
||||
func T(s string) string {
|
||||
if preferredLanguage == defaultLanguage {
|
||||
return s
|
||||
|
|
|
@ -69,6 +69,11 @@ func (p *BuildrootProvisioner) String() string {
|
|||
return "buildroot"
|
||||
}
|
||||
|
||||
// CompatibleWithHost checks if provisioner is compatible with host
|
||||
func (p *BuildrootProvisioner) CompatibleWithHost() bool {
|
||||
return p.OsReleaseInfo.ID == "buildroot"
|
||||
}
|
||||
|
||||
// escapeSystemdDirectives escapes special characters in the input variables used to create the
|
||||
// systemd unit file, which would otherwise be interpreted as systemd directives. An example
|
||||
// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically
|
||||
|
|
|
@ -36,7 +36,7 @@ func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
|
|||
lockErr := lock.TryLock()
|
||||
if lockErr != nil {
|
||||
glog.Warningf("temporary error : %v", lockErr.Error())
|
||||
return errors.Wrapf(lockErr, "falied to acquire lock for %s > ", filename)
|
||||
return errors.Wrapf(lockErr, "failed to acquire lock for %s > ", filename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -200,14 +200,3 @@ func ConcatStrings(src []string, prefix string, postfix string) []string {
|
|||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// ContainsString checks if a given slice of strings contains the provided string.
|
||||
// If a modifier func is provided, it is called with the slice item before the comparation.
|
||||
func ContainsString(slice []string, s string) bool {
|
||||
for _, item := range slice {
|
||||
if item == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -45,5 +45,5 @@ Then minikube is for you.
|
|||
|
||||
## Where should I go next?
|
||||
|
||||
* [Getting Started](/start/): Get started with minikube
|
||||
* [Examples](/examples/): Check out some minikube examples!
|
||||
* [Getting Started](/docs/start/): Get started with minikube
|
||||
* [Examples](/docs/examples/): Check out some minikube examples!
|
||||
|
|
|
@ -27,3 +27,16 @@ virt-host-validate
|
|||
curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2 \
|
||||
&& sudo install docker-machine-driver-kvm2 /usr/local/bin/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To explicitly start minikube with KVM:
|
||||
|
||||
```shell
|
||||
minikube start --vm-driver=kvm2
|
||||
```
|
||||
To make KVM the default driver:
|
||||
|
||||
```shell
|
||||
minikube config set vm-driver kvm2
|
||||
```
|
||||
|
|
|
@ -32,6 +32,21 @@ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin
|
|||
{{% /tab %}}
|
||||
{{% /tabs %}}
|
||||
|
||||
### Upgrading minikube
|
||||
|
||||
{{% tabs %}}
|
||||
{{% tab "Brew" %}}
|
||||
|
||||
If the [Brew Package Manager](https://brew.sh/) is installed, use it to download and upgrade minikube:
|
||||
|
||||
```shell
|
||||
rm /usr/local/bin/minikube
|
||||
brew cask reinstall minikube
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% /tabs %}}
|
||||
|
||||
## Hypervisor Setup
|
||||
|
||||
{{% tabs %}}
|
||||
|
|
|
@ -35,4 +35,4 @@ If you are looking for a solution tuned for iterative application development, c
|
|||
|
||||
- [Draft](https://draft.sh): see specific [minikube instructions](https://github.com/Azure/draft/blob/master/docs/install-minikube.md)
|
||||
- [Okteto](https://github.com/okteto/okteto)
|
||||
- [Skaffold](http://github.com/ContainerTools/skaffold)
|
||||
- [Skaffold](https://github.com/GoogleContainerTools/skaffold)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// +build integration
|
||||
|
||||
/*
|
||||
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 integration
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
p := profileName(t)
|
||||
mk := NewMinikubeRunner(t, p, "--wait=false")
|
||||
|
||||
tests := []struct {
|
||||
cmd string
|
||||
stdout string
|
||||
stderr string
|
||||
}{
|
||||
{
|
||||
cmd: "config unset cpus",
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
},
|
||||
{
|
||||
cmd: "config get cpus",
|
||||
stdout: "",
|
||||
stderr: "Error: specified key could not be found in config",
|
||||
},
|
||||
{
|
||||
cmd: "config set cpus 2",
|
||||
stdout: "! These changes will take effect upon a minikube delete and then a minikube start",
|
||||
stderr: "",
|
||||
},
|
||||
{
|
||||
cmd: "config get cpus",
|
||||
stdout: "2",
|
||||
stderr: "",
|
||||
},
|
||||
{
|
||||
cmd: "config unset cpus",
|
||||
stdout: "",
|
||||
stderr: ""},
|
||||
{
|
||||
cmd: "config get cpus",
|
||||
stdout: "",
|
||||
stderr: "Error: specified key could not be found in config",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
stdout, stderr, _ := mk.RunCommandRetriable(tc.cmd)
|
||||
|
||||
if !compare(tc.stdout, stdout) {
|
||||
t.Fatalf("Expected stdout to be: %s. Stdout was: %s Stderr: %s", tc.stdout, stdout, stderr)
|
||||
}
|
||||
if !compare(tc.stderr, stderr) {
|
||||
t.Fatalf("Expected stderr to be: %s. Stdout was: %s Stderr: %s", tc.stderr, stdout, stderr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func compare(s1, s2 string) bool {
|
||||
return strings.TrimSpace(s1) == strings.TrimSpace(s2)
|
||||
}
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
||||
|
@ -107,13 +107,13 @@ func deleteUntrustedWorkload(t *testing.T, profile string) {
|
|||
|
||||
// waitForGvisorControllerRunning waits for the gvisor controller pod to be running
|
||||
func waitForGvisorControllerRunning(p string) error {
|
||||
client, err := commonutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"kubernetes.io/minikube-addons": "gvisor"}))
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
return errors.Wrap(err, "waiting for gvisor controller pod to stabilize")
|
||||
}
|
||||
return nil
|
||||
|
@ -121,13 +121,13 @@ func waitForGvisorControllerRunning(p string) error {
|
|||
|
||||
// waitForUntrustedNginxRunning waits for the untrusted nginx pod to start running
|
||||
func waitForUntrustedNginxRunning(miniProfile string) error {
|
||||
client, err := commonutil.GetClient(miniProfile)
|
||||
client, err := kapi.Client(miniProfile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
return errors.Wrap(err, "waiting for nginx pods")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
var startTimeout = flag.Int("timeout", 25, "number of minutes to wait for minikube start")
|
||||
var startTimeout = flag.Duration("timeout", 25*time.Minute, "max duration to wait for a full minikube start")
|
||||
var binaryPath = flag.String("binary", "../../out/minikube", "path to minikube binary")
|
||||
var globalArgs = flag.String("minikube-args", "", "Arguments to pass to minikube")
|
||||
var startArgs = flag.String("minikube-start-args", "", "Arguments to pass to minikube start")
|
||||
|
@ -45,10 +45,10 @@ func NewMinikubeRunner(t *testing.T, profile string, extraStartArgs ...string) u
|
|||
return util.MinikubeRunner{
|
||||
Profile: profile,
|
||||
BinaryPath: *binaryPath,
|
||||
StartArgs: *startArgs + " " + strings.Join(extraStartArgs, " "),
|
||||
StartArgs: *startArgs + " --wait-timeout=13m " + strings.Join(extraStartArgs, " "), // adding timeout per component
|
||||
GlobalArgs: *globalArgs,
|
||||
MountArgs: *mountArgs,
|
||||
TimeOutStart: time.Duration(*startTimeout) * time.Minute,
|
||||
TimeOutStart: *startTimeout, // timeout for all start
|
||||
T: t,
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func profileName(t *testing.T) string {
|
|||
return p
|
||||
}
|
||||
|
||||
// shouldRunInParallel deterimines if test should run in parallel or not
|
||||
// shouldRunInParallel determines if test should run in parallel or not
|
||||
func shouldRunInParallel(t *testing.T) bool {
|
||||
t.Helper()
|
||||
if !*parallel {
|
||||
|
|
|
@ -34,8 +34,7 @@ import (
|
|||
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
pkgutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
@ -43,12 +42,12 @@ import (
|
|||
func testAddons(t *testing.T) {
|
||||
t.Parallel()
|
||||
p := profileName(t)
|
||||
client, err := pkgutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get kubernetes client: %v", err)
|
||||
}
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"component": "kube-addon-manager"}))
|
||||
if err := pkgutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
t.Errorf("Error waiting for addon manager to be up")
|
||||
}
|
||||
}
|
||||
|
@ -193,22 +192,22 @@ func testRegistry(t *testing.T) {
|
|||
p := profileName(t)
|
||||
mk := NewMinikubeRunner(t, p)
|
||||
mk.RunCommand("addons enable registry", true)
|
||||
client, err := pkgutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
if err != nil {
|
||||
t.Fatalf("getting kubernetes client: %v", err)
|
||||
}
|
||||
if err := pkgutil.WaitForRCToStabilize(client, "kube-system", "registry", time.Minute*5); err != nil {
|
||||
if err := kapi.WaitForRCToStabilize(client, "kube-system", "registry", time.Minute*5); err != nil {
|
||||
t.Fatalf("waiting for registry replicacontroller to stabilize: %v", err)
|
||||
}
|
||||
rs := labels.SelectorFromSet(labels.Set(map[string]string{"actual-registry": "true"}))
|
||||
if err := pkgutil.WaitForPodsWithLabelRunning(client, "kube-system", rs); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", rs); err != nil {
|
||||
t.Fatalf("waiting for registry pods: %v", err)
|
||||
}
|
||||
ps, err := labels.Parse("kubernetes.io/minikube-addons=registry,actual-registry!=true")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to parse selector: %v", err)
|
||||
}
|
||||
if err := pkgutil.WaitForPodsWithLabelRunning(client, "kube-system", ps); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", ps); err != nil {
|
||||
t.Fatalf("waiting for registry-proxy pods: %v", err)
|
||||
}
|
||||
ip, stderr := mk.RunCommand("ip", true)
|
||||
|
@ -265,18 +264,18 @@ func testRegistry(t *testing.T) {
|
|||
|
||||
// waitForNginxRunning waits for nginx service to be up
|
||||
func waitForNginxRunning(t *testing.T, miniProfile string) error {
|
||||
client, err := commonutil.GetClient(miniProfile)
|
||||
client, err := kapi.Client(miniProfile)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
return errors.Wrap(err, "waiting for nginx pods")
|
||||
}
|
||||
|
||||
if err := commonutil.WaitForService(client, "default", "nginx", true, time.Millisecond*500, time.Minute*10); err != nil {
|
||||
if err := kapi.WaitForService(client, "default", "nginx", true, time.Millisecond*500, time.Minute*10); err != nil {
|
||||
t.Errorf("Error waiting for nginx service to be up")
|
||||
}
|
||||
return nil
|
||||
|
@ -284,17 +283,17 @@ func waitForNginxRunning(t *testing.T, miniProfile string) error {
|
|||
|
||||
// waitForIngressControllerRunning waits until ingress controller pod to be running
|
||||
func waitForIngressControllerRunning(miniProfile string) error {
|
||||
client, err := commonutil.GetClient(miniProfile)
|
||||
client, err := kapi.Client(miniProfile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
|
||||
if err := commonutil.WaitForDeploymentToStabilize(client, "kube-system", "nginx-ingress-controller", time.Minute*10); err != nil {
|
||||
if err := kapi.WaitForDeploymentToStabilize(client, "kube-system", "nginx-ingress-controller", time.Minute*10); err != nil {
|
||||
return errors.Wrap(err, "waiting for ingress-controller deployment to stabilize")
|
||||
}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"app.kubernetes.io/name": "nginx-ingress-controller"}))
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
return errors.Wrap(err, "waiting for ingress-controller pods")
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
pkgutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
@ -34,7 +34,7 @@ import (
|
|||
func testClusterDNS(t *testing.T) {
|
||||
t.Parallel()
|
||||
p := profileName(t)
|
||||
client, err := pkgutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting kubernetes client %v", err)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
pkgutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/util/lock"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
|
@ -132,12 +132,12 @@ func writeFilesFromHost(mountedDir string, files []string, content string) error
|
|||
}
|
||||
|
||||
func waitForPods(s map[string]string, profile string) error {
|
||||
client, err := pkgutil.GetClient(profile)
|
||||
client, err := kapi.Client(profile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting kubernetes client: %v", err)
|
||||
}
|
||||
selector := labels.SelectorFromSet(labels.Set(s))
|
||||
if err := pkgutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
core "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
@ -73,13 +73,13 @@ func testProvisioning(t *testing.T) {
|
|||
// Check that the storage provisioner pod is running
|
||||
|
||||
checkPodRunning := func() error {
|
||||
client, err := commonutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"integration-test": "storage-provisioner"}))
|
||||
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -31,8 +31,8 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
"k8s.io/minikube/pkg/minikube/tunnel"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
"k8s.io/minikube/test/integration/util"
|
||||
)
|
||||
|
@ -70,18 +70,18 @@ func testTunnel(t *testing.T) {
|
|||
t.Fatalf("creating nginx ingress resource: %s", err)
|
||||
}
|
||||
|
||||
client, err := commonutil.GetClient(p)
|
||||
client, err := kapi.Client(p)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(errors.Wrap(err, "getting kubernetes client"))
|
||||
}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx-svc"}))
|
||||
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
if err := kapi.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
|
||||
t.Fatal(errors.Wrap(err, "waiting for nginx pods"))
|
||||
}
|
||||
|
||||
if err := commonutil.WaitForService(client, "default", "nginx-svc", true, 1*time.Second, 2*time.Minute); err != nil {
|
||||
if err := kapi.WaitForService(client, "default", "nginx-svc", true, 1*time.Second, 2*time.Minute); err != nil {
|
||||
t.Fatal(errors.Wrap(err, "Error waiting for nginx service to be up"))
|
||||
}
|
||||
|
||||
|
@ -114,14 +114,14 @@ func testTunnel(t *testing.T) {
|
|||
func getIngress(kr *util.KubectlRunner) (string, error) {
|
||||
nginxIP := ""
|
||||
var ret error
|
||||
err := wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
|
||||
err := wait.PollImmediate(1*time.Second, 2*time.Minute, func() (bool, error) {
|
||||
cmd := []string{"get", "svc", "nginx-svc", "-o", "jsonpath={.status.loadBalancer.ingress[0].ip}"}
|
||||
stdout, err := kr.RunCommand(cmd)
|
||||
switch {
|
||||
case err == nil:
|
||||
nginxIP = string(stdout)
|
||||
return len(stdout) != 0, nil
|
||||
case !commonutil.IsRetryableAPIError(err):
|
||||
case !kapi.IsRetryableAPIError(err):
|
||||
ret = fmt.Errorf("`%s` failed with non retriable error: %v", cmd, err)
|
||||
return false, err
|
||||
default:
|
||||
|
|
|
@ -27,6 +27,8 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
func TestNone(t *testing.T) {
|
||||
|
@ -76,7 +78,7 @@ func testNoneMinikubeFolderPermissions(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("Failed to convert uid to int: %v", err)
|
||||
}
|
||||
info, err := os.Stat(filepath.Join(u.HomeDir, ".minikube"))
|
||||
info, err := os.Stat(constants.GetMinipath())
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get .minikube dir info, %v", err)
|
||||
}
|
||||
|
|
|
@ -23,17 +23,17 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/kapi"
|
||||
)
|
||||
|
||||
// WaitForBusyboxRunning waits until busybox pod to be running
|
||||
func WaitForBusyboxRunning(t *testing.T, namespace string, miniProfile string) error {
|
||||
client, err := commonutil.GetClient(miniProfile)
|
||||
client, err := kapi.Client(miniProfile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting kubernetes client")
|
||||
}
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{"integration-test": "busybox"}))
|
||||
return commonutil.WaitForPodsWithLabelRunning(client, namespace, selector)
|
||||
return kapi.WaitForPodsWithLabelRunning(client, namespace, selector)
|
||||
}
|
||||
|
||||
// Logf writes logs to stdout if -v is set.
|
||||
|
|
|
@ -124,7 +124,7 @@ func (m *MinikubeRunner) RunCommand(cmdStr string, failError bool, waitForRun ..
|
|||
return stdout, stderr
|
||||
}
|
||||
|
||||
// RunCommandRetriable Error executes a command, returns error
|
||||
// RunCommandRetriable executes a command, returns error
|
||||
// the purpose of this command is to make it retriable and
|
||||
// better logging for retrying
|
||||
func (m *MinikubeRunner) RunCommandRetriable(cmdStr string, waitForRun ...bool) (stdout string, stderr string, err error) {
|
||||
|
@ -244,7 +244,7 @@ func (m *MinikubeRunner) TearDown(t *testing.T) {
|
|||
profileArg := fmt.Sprintf("-p=%s", m.Profile)
|
||||
path, _ := filepath.Abs(m.BinaryPath)
|
||||
cmd := exec.Command(path, profileArg, "delete")
|
||||
err := cmd.Start()
|
||||
err := cmd.Start() // don't wait for it to finish
|
||||
if err != nil {
|
||||
t.Errorf("error tearing down minikube %s : %v", profileArg, err)
|
||||
}
|
||||
|
|
|
@ -73,10 +73,14 @@ func TestVersionUpgrade(t *testing.T) {
|
|||
}
|
||||
defer os.Remove(fname)
|
||||
|
||||
mkCurrent := NewMinikubeRunner(t, p)
|
||||
defer mkCurrent.TearDown(t)
|
||||
mkHead := NewMinikubeRunner(t, p) // minikube from HEAD.
|
||||
defer mkHead.TearDown(t)
|
||||
|
||||
mkRelease := NewMinikubeRunner(t, p)
|
||||
mkRelease := NewMinikubeRunner(t, p) // lastest publicly released version minikbue.
|
||||
|
||||
// because the --wait-timeout is a new flag and the current latest release (1.3.1) doesn't have it
|
||||
// this won't be necessary after we release the change with --wait-timeout flag
|
||||
mkRelease.StartArgs = strings.Replace("mkRelease.StartArgs", "--wait-timeout=13m", "", 1)
|
||||
mkRelease.BinaryPath = fname
|
||||
// For full coverage: also test upgrading from oldest to newest supported k8s release
|
||||
stdout, stderr, err := mkRelease.Start(fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion))
|
||||
|
@ -89,9 +93,9 @@ func TestVersionUpgrade(t *testing.T) {
|
|||
mkRelease.CheckStatus(state.Stopped.String())
|
||||
|
||||
// Trim the leading "v" prefix to assert that we handle it properly.
|
||||
stdout, stderr, err = mkCurrent.Start(fmt.Sprintf("--kubernetes-version=%s", strings.TrimPrefix(constants.NewestKubernetesVersion, "v")))
|
||||
stdout, stderr, err = mkHead.Start(fmt.Sprintf("--kubernetes-version=%s", strings.TrimPrefix(constants.NewestKubernetesVersion, "v")))
|
||||
if err != nil {
|
||||
t.Fatalf("TestVersionUpgrade mkCurrent.Start start failed : %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
|
||||
}
|
||||
mkCurrent.CheckStatus(state.Running.String())
|
||||
mkHead.CheckStatus(state.Running.String())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue