Merge branch 'master' into retry-cgroups
commit
1f4bfa195e
|
@ -794,7 +794,7 @@ jobs:
|
|||
cp minikube-darwin-amd64 minikube
|
||||
chmod a+x minikube*
|
||||
START_TIME=$(date -u +%s)
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--vm-driver=virtualbox -test.run "(TestAddons|TestCertOptions|TestSkaffold)" -test.timeout=15m -test.v -timeout-multiplier=3 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--vm-driver=virtualbox -test.run "(TestAddons|TestCertOptions|TestSkaffold)" -test.timeout=20m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
END_TIME=$(date -u +%s)
|
||||
TIME_ELAPSED=$(($END_TIME-$START_TIME))
|
||||
min=$((${TIME_ELAPSED}/60))
|
||||
|
@ -980,7 +980,7 @@ jobs:
|
|||
chmod a+x e2e-*
|
||||
chmod a+x minikube-*
|
||||
START_TIME=$(date -u +%s)
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--driver=virtualbox -test.run "TestMultiNode" -test.timeout=15m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--driver=virtualbox -test.run "TestMultiNode" -test.timeout=17m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
END_TIME=$(date -u +%s)
|
||||
TIME_ELAPSED=$(($END_TIME-$START_TIME))
|
||||
min=$((${TIME_ELAPSED}/60))
|
||||
|
|
|
@ -792,7 +792,7 @@ jobs:
|
|||
cp minikube-darwin-amd64 minikube
|
||||
chmod a+x minikube*
|
||||
START_TIME=$(date -u +%s)
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--vm-driver=virtualbox -test.run "(TestAddons|TestCertOptions|TestSkaffold)" -test.timeout=15m -test.v -timeout-multiplier=3 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--vm-driver=virtualbox -test.run "(TestAddons|TestCertOptions|TestSkaffold)" -test.timeout=20m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
END_TIME=$(date -u +%s)
|
||||
TIME_ELAPSED=$(($END_TIME-$START_TIME))
|
||||
min=$((${TIME_ELAPSED}/60))
|
||||
|
@ -978,7 +978,7 @@ jobs:
|
|||
chmod a+x e2e-*
|
||||
chmod a+x minikube-*
|
||||
START_TIME=$(date -u +%s)
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--driver=virtualbox -test.run "TestMultiNode" -test.timeout=15m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome ./e2e-darwin-amd64 -minikube-start-args=--driver=virtualbox -test.run "TestMultiNode" -test.timeout=17m -test.v -timeout-multiplier=1.5 -binary=./minikube-darwin-amd64 2>&1 | tee ./report/testout.txt
|
||||
END_TIME=$(date -u +%s)
|
||||
TIME_ELAPSED=$(($END_TIME-$START_TIME))
|
||||
min=$((${TIME_ELAPSED}/60))
|
||||
|
|
41
CHANGELOG.md
41
CHANGELOG.md
|
@ -1,5 +1,46 @@
|
|||
# Release Notes
|
||||
|
||||
## Version 1.12.3 - 2020-08-12
|
||||
|
||||
Features:
|
||||
|
||||
* Make waiting for Host configurable via --wait-timeout flag [#8948](https://github.com/kubernetes/minikube/pull/8948)
|
||||
|
||||
Bug Fixes:
|
||||
|
||||
* Ignore localhost proxy started with scheme. [#8885](https://github.com/kubernetes/minikube/pull/8885)
|
||||
* Improve error handling for validating memory limits [#8959](https://github.com/kubernetes/minikube/pull/8959)
|
||||
* Skip validations if --force is supplied [#8969](https://github.com/kubernetes/minikube/pull/8969)
|
||||
* Fix handling of parseIP error [#8820](https://github.com/kubernetes/minikube/pull/8820)
|
||||
|
||||
Improvements:
|
||||
|
||||
* GCP Auth Addon: Exit with better error messages [#8932](https://github.com/kubernetes/minikube/pull/8932)
|
||||
* Add warning for ingress addon enabled with driver of none [#8870](https://github.com/kubernetes/minikube/pull/8870)
|
||||
* Update Japanese translation [#8967](https://github.com/kubernetes/minikube/pull/8967)
|
||||
* Fix for a few typos in polish translations [#8950](https://github.com/kubernetes/minikube/pull/8950)
|
||||
|
||||
Thank you to our contributors for this release!
|
||||
|
||||
- Anders F Björklund
|
||||
- Andrej Guran
|
||||
- Chris Paika
|
||||
- Dean Coakley
|
||||
- Evgeny Shmarnev
|
||||
- Ling Samuel
|
||||
- Ma Xinjian
|
||||
- Marcin Niemira
|
||||
- Medya Ghazizadeh
|
||||
- Pablo Caderno
|
||||
- Priya Wadhwa
|
||||
- RA489
|
||||
- Sharif Elgamal
|
||||
- TAKAHASHI Shuuji
|
||||
- Thomas Strömberg
|
||||
- inductor
|
||||
- priyawadhwa
|
||||
- programistka
|
||||
|
||||
## Version 1.12.2 - 2020-08-03
|
||||
|
||||
Features:
|
||||
|
|
59
Makefile
59
Makefile
|
@ -15,7 +15,7 @@
|
|||
# Bump these on release - and please check ISO_VERSION for correctness.
|
||||
VERSION_MAJOR ?= 1
|
||||
VERSION_MINOR ?= 12
|
||||
VERSION_BUILD ?= 2
|
||||
VERSION_BUILD ?= 3
|
||||
RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
|
||||
VERSION ?= v$(RAW_VERSION)
|
||||
|
||||
|
@ -34,6 +34,7 @@ GO_VERSION ?= 1.14.6
|
|||
INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1)
|
||||
BUILDROOT_BRANCH ?= 2019.02.11
|
||||
REGISTRY?=gcr.io/k8s-minikube
|
||||
REGISTRY_GH?=docker.pkg.github.com/kubernetes/minikube
|
||||
|
||||
# Get git commit id
|
||||
COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
|
||||
|
@ -46,6 +47,10 @@ BUILD_IMAGE ?= us.gcr.io/k8s-artifacts-prod/build-image/kube-cross:v$(GO_VERSIO
|
|||
ISO_BUILD_IMAGE ?= $(REGISTRY)/buildroot-image
|
||||
KVM_BUILD_IMAGE ?= $(REGISTRY)/kvm-build-image:$(GO_VERSION)
|
||||
|
||||
KIC_BASE_IMAGE_GCR ?= $(REGISTRY)/kicbase:$(KIC_VERSION)
|
||||
KIC_BASE_IMAGE_GH ?= $(REGISTRY_GH)/kicbase:$(KIC_VERSION)
|
||||
KIC_BASE_IMAGE_HUB ?= kicbase/stable:$(KIC_VERSION)
|
||||
|
||||
ISO_BUCKET ?= minikube/iso
|
||||
|
||||
MINIKUBE_VERSION ?= $(ISO_VERSION)
|
||||
|
@ -130,6 +135,20 @@ KVM2_LDFLAGS := -X k8s.io/minikube/pkg/drivers/kvm.version=$(VERSION) -X k8s.io/
|
|||
# hyperkit ldflags
|
||||
HYPERKIT_LDFLAGS := -X k8s.io/minikube/pkg/drivers/hyperkit.version=$(VERSION) -X k8s.io/minikube/pkg/drivers/hyperkit.gitCommitID=$(COMMIT)
|
||||
|
||||
# autopush artefacts
|
||||
AUTOPUSH ?=
|
||||
|
||||
# don't ask for user confirmation
|
||||
IN_CI := false
|
||||
|
||||
# $(call user_confirm, message)
|
||||
define user_confirm
|
||||
@if [ "${IN_CI}" = "false" ]; then\
|
||||
echo "⚠️ $(1)";\
|
||||
read -p "Do you want to proceed? (Y/N): " confirm && echo $$confirm | grep -iq "^[yY]" || exit 1;\
|
||||
fi
|
||||
endef
|
||||
|
||||
# $(call DOCKER, image, command)
|
||||
define DOCKER
|
||||
docker run --rm -e GOCACHE=/app/.cache -e IN_DOCKER=1 --user $(shell id -u):$(shell id -g) -w /app -v $(PWD):/app -v $(GOPATH):/go --init $(1) /bin/bash -c '$(2)'
|
||||
|
@ -530,9 +549,12 @@ storage-provisioner-image: out/storage-provisioner-$(GOARCH) ## Build storage-pr
|
|||
|
||||
.PHONY: kic-base-image
|
||||
kic-base-image: ## builds the base image used for kic.
|
||||
docker rmi -f $(REGISTRY)/kicbase:$(KIC_VERSION)-snapshot || true
|
||||
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION)-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(REGISTRY)/kicbase:$(KIC_VERSION) --target base ./deploy/kicbase
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(REGISTRY)/kicbase:$(KIC_VERSION)-snapshot
|
||||
docker rmi -f $(KIC_BASE_IMAGE_GCR)-snapshot || true
|
||||
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION)-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(KIC_BASE_IMAGE_GCR) --target base ./deploy/kicbase
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GCR)-snapshot
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GCR)
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_HUB)
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GH)
|
||||
|
||||
.PHONY: upload-preloaded-images-tar
|
||||
upload-preloaded-images-tar: out/minikube # Upload the preloaded images for oldest supported, newest supported, and default kubernetes versions to GCS.
|
||||
|
@ -543,6 +565,35 @@ upload-preloaded-images-tar: out/minikube # Upload the preloaded images for olde
|
|||
push-storage-provisioner-image: storage-provisioner-image ## Push storage-provisioner docker image using gcloud
|
||||
gcloud docker -- push $(STORAGE_PROVISIONER_IMAGE)
|
||||
|
||||
.PHONY: push-docker
|
||||
push-docker: # Push docker image base on to IMAGE variable
|
||||
(docker pull $(IMAGE) && (echo "Image already exist"; exit 1) || echo "Image doesn't exist in registry")
|
||||
ifndef AUTOPUSH
|
||||
$(call user_confirm, 'Are you sure you want to push $(IMAGE) ?')
|
||||
endif
|
||||
docker push $(IMAGE) || gcloud docker -- push $(IMAGE)
|
||||
|
||||
.PHONY: push-kic-base-image-gcr
|
||||
push-kic-base-image-gcr: kic-base-image ## Push kic-base to gcr
|
||||
$(MAKE) push-docker IMAGE=$(KIC_BASE_IMAGE_GCR)
|
||||
|
||||
.PHONY: push-kic-base-image-gh
|
||||
push-kic-base-image-gh: kic-base-image ## Push kic-base to github
|
||||
$(MAKE) push-docker IMAGE=$(KIC_BASE_IMAGE_GH)
|
||||
|
||||
.PHONY: push-kic-base-image-hub
|
||||
push-kic-base-image-hub: kic-base-image ## Push kic-base to docker hub
|
||||
$(MAKE) push-docker IMAGE=$(KIC_BASE_IMAGE_HUB)
|
||||
|
||||
.PHONY: push-kic-base-image
|
||||
push-kic-base-image: ## Push kic-base to all registries
|
||||
ifndef AUTOPUSH
|
||||
$(call user_confirm, 'Are you sure you want to push: $(KIC_BASE_IMAGE_GH) & $(KIC_BASE_IMAGE_GCR) & $(KIC_BASE_IMAGE_HUB) ?')
|
||||
$(MAKE) push-kic-base-image AUTOPUSH=true
|
||||
else
|
||||
$(MAKE) push-kic-base-image-gh push-kic-base-image-gcr push-kic-base-image-hub
|
||||
endif
|
||||
|
||||
.PHONY: out/gvisor-addon
|
||||
out/gvisor-addon: pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go ## Build gvisor addon
|
||||
GOOS=linux CGO_ENABLED=0 go build -o $@ cmd/gvisor/gvisor.go
|
||||
|
|
|
@ -135,6 +135,9 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
displayEnviron(os.Environ())
|
||||
if viper.GetBool(force) {
|
||||
out.WarningT("minikube skips various validations when --force is supplied; this may lead to unexpected behavior")
|
||||
}
|
||||
|
||||
// if --registry-mirror specified when run minikube start,
|
||||
// take arg precedence over MINIKUBE_REGISTRY_MIRROR
|
||||
|
@ -662,7 +665,7 @@ func validateDriver(ds registry.DriverState, existing *config.ClusterConfig) {
|
|||
}
|
||||
out.ErrLn("")
|
||||
|
||||
if !st.Installed && !viper.GetBool(force) {
|
||||
if !st.Installed {
|
||||
if existing != nil {
|
||||
if old := hostDriver(existing); name == old {
|
||||
exit.WithCodeT(exit.Unavailable, "{{.driver}} does not appear to be installed, but is specified by an existing profile. Please run 'minikube delete' or install {{.driver}}", out.V{"driver": name})
|
||||
|
@ -670,10 +673,7 @@ func validateDriver(ds registry.DriverState, existing *config.ClusterConfig) {
|
|||
}
|
||||
exit.WithCodeT(exit.Unavailable, "{{.driver}} does not appear to be installed", out.V{"driver": name})
|
||||
}
|
||||
|
||||
if !viper.GetBool(force) {
|
||||
exit.WithCodeT(exit.Unavailable, "Failed to validate '{{.driver}}' driver", out.V{"driver": name})
|
||||
}
|
||||
exitIfNotForced(exit.Unavailable, "Failed to validate '{{.driver}}' driver", out.V{"driver": name})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,11 +866,10 @@ func validateMemorySize(req int, drvName string) {
|
|||
// a more sane alternative to their high memory 80%
|
||||
minAdvised := 0.50 * float64(sysLimit)
|
||||
|
||||
if req < minUsableMem && !viper.GetBool(force) {
|
||||
exit.WithCodeT(exit.Config, "Requested memory allocation {{.requested}}MB is less than the usable minimum of {{.minimum_memory}}MB",
|
||||
out.V{"requested": req, "minimum_memory": minUsableMem})
|
||||
if req < minUsableMem {
|
||||
exitIfNotForced(exit.Config, "Requested memory allocation {{.requested}}MB is less than the usable minimum of {{.minimum_memory}}MB", out.V{"requested": req, "minimum_memory": minUsableMem})
|
||||
}
|
||||
if req < minRecommendedMem && !viper.GetBool(force) {
|
||||
if req < minRecommendedMem {
|
||||
out.WarningT("Requested memory allocation ({{.requested}}MB) is less than the recommended minimum {{.recommended}}MB. Kubernetes may crash unexpectedly.",
|
||||
out.V{"requested": req, "recommended": minRecommendedMem})
|
||||
}
|
||||
|
@ -883,24 +882,21 @@ func validateMemorySize(req int, drvName string) {
|
|||
`, out.V{"container_limit": containerLimit, "system_limit": sysLimit})
|
||||
}
|
||||
|
||||
if req > sysLimit && !viper.GetBool(force) {
|
||||
out.T(out.Tip, "To suppress memory validations you can use --force flag.")
|
||||
exit.WithCodeT(exit.Config, `Requested memory allocation {{.requested}}MB is more than your system limit {{.system_limit}}MB. Try specifying a lower memory:
|
||||
|
||||
miniube start --memory={{.min_advised}}mb
|
||||
|
||||
`,
|
||||
out.V{"requested": req, "system_limit": sysLimit, "max_advised": int32(maxAdvised), "min_advised": minAdvised})
|
||||
if req > sysLimit {
|
||||
message := `Requested memory allocation {{.requested}}MB is more than your system limit {{.system_limit}}MB. Try specifying a lower memory:
|
||||
|
||||
miniube start --memory={{.min_advised}}mb
|
||||
|
||||
`
|
||||
exitIfNotForced(exit.Config, message, out.V{"requested": req, "system_limit": sysLimit, "max_advised": int32(maxAdvised), "min_advised": minAdvised})
|
||||
}
|
||||
|
||||
if float64(req) > maxAdvised && !viper.GetBool(force) {
|
||||
if float64(req) > maxAdvised {
|
||||
out.WarningT(`You are allocating {{.requested}}MB to memory and your system only has {{.system_limit}}MB. You might face issues. try specifying a lower memory:
|
||||
|
||||
miniube start --memory={{.min_advised}}mb
|
||||
|
||||
`, out.V{"requested": req, "system_limit": sysLimit, "min_advised": minAdvised})
|
||||
out.T(out.Tip, "To suppress and ignore this warning you can use --force flag.")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -919,8 +915,8 @@ func validateCPUCount(drvName string) {
|
|||
} else {
|
||||
cpuCount = viper.GetInt(cpus)
|
||||
}
|
||||
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})
|
||||
if cpuCount < minimumCPUS {
|
||||
exitIfNotForced(exit.BadUsage, "Requested cpu count {{.requested_cpus}} is less than the minimum allowed of {{.minimum_cpus}}", out.V{"requested_cpus": cpuCount, "minimum_cpus": minimumCPUS})
|
||||
}
|
||||
|
||||
if driver.IsKIC((drvName)) {
|
||||
|
@ -942,22 +938,22 @@ func validateCPUCount(drvName string) {
|
|||
`)
|
||||
}
|
||||
out.T(out.Documentation, "https://docs.docker.com/config/containers/resource_constraints/")
|
||||
exit.UsageT("Ensure your {{.driver_name}} system has enough CPUs. The minimum allowed is 2 CPUs.", out.V{"driver_name": driver.FullName(viper.GetString("driver"))})
|
||||
|
||||
exitIfNotForced(exit.BadUsage, "Ensure your {{.driver_name}} system has enough CPUs. The minimum allowed is 2 CPUs.", out.V{"driver_name": driver.FullName(viper.GetString("driver"))})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validateFlags validates the supplied flags against known bad combinations
|
||||
func validateFlags(cmd *cobra.Command, drvName string) {
|
||||
|
||||
if cmd.Flags().Changed(humanReadableDiskSize) {
|
||||
diskSizeMB, err := util.CalculateSizeInMB(viper.GetString(humanReadableDiskSize))
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Config, "Validation unable to parse disk size '{{.diskSize}}': {{.error}}", out.V{"diskSize": viper.GetString(humanReadableDiskSize), "error": err})
|
||||
exitIfNotForced(exit.Config, "Validation unable to parse disk size '{{.diskSize}}': {{.error}}", out.V{"diskSize": viper.GetString(humanReadableDiskSize), "error": err})
|
||||
}
|
||||
|
||||
if diskSizeMB < 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": minimumDiskSize})
|
||||
if diskSizeMB < minimumDiskSize {
|
||||
exitIfNotForced(exit.Config, "Requested disk size {{.requested_size}} is less than minimum of {{.minimum_size}}", out.V{"requested_size": diskSizeMB, "minimum_size": minimumDiskSize})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,7 +971,7 @@ func validateFlags(cmd *cobra.Command, drvName string) {
|
|||
}
|
||||
req, err := util.CalculateSizeInMB(viper.GetString(memory))
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Config, "Unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": viper.GetString(memory), "error": err})
|
||||
exitIfNotForced(exit.Config, "Unable to parse memory '{{.memory}}': {{.error}}", out.V{"memory": viper.GetString(memory), "error": err})
|
||||
}
|
||||
validateMemorySize(req, drvName)
|
||||
}
|
||||
|
@ -1153,11 +1149,10 @@ func validateKubernetesVersion(old *config.ClusterConfig) {
|
|||
|
||||
if nvs.LT(oldestVersion) {
|
||||
out.WarningT("Specified Kubernetes version {{.specified}} is less than the oldest supported version: {{.oldest}}", out.V{"specified": nvs, "oldest": constants.OldestKubernetesVersion})
|
||||
if viper.GetBool(force) {
|
||||
out.WarningT("Kubernetes {{.version}} is not supported by this release of minikube", out.V{"version": nvs})
|
||||
} else {
|
||||
exit.WithCodeT(exit.Data, "Sorry, Kubernetes {{.version}} is not supported by this release of minikube. To use this version anyway, use the `--force` flag.", out.V{"version": nvs})
|
||||
if !viper.GetBool(force) {
|
||||
out.WarningT("You can force an unsupported Kubernetes version via the --force flag")
|
||||
}
|
||||
exitIfNotForced(exit.Data, "Kubernetes {{.version}} is not supported by this release of minikube", out.V{"version": nvs})
|
||||
}
|
||||
|
||||
if old == nil || old.KubernetesConfig.KubernetesVersion == "" {
|
||||
|
@ -1220,3 +1215,10 @@ func getKubernetesVersion(old *config.ClusterConfig) string {
|
|||
|
||||
return version.VersionPrefix + nvs.String()
|
||||
}
|
||||
|
||||
func exitIfNotForced(code int, message string, v out.V) {
|
||||
if !viper.GetBool(force) {
|
||||
exit.WithCodeT(code, message, v)
|
||||
}
|
||||
out.WarningT(message, v)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ RUN sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/lib
|
|||
RUN sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.18:/1.18.3/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list" && \
|
||||
curl -LO https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.18:/1.18.3/xUbuntu_20.04/Release.key && \
|
||||
apt-key add - < Release.key && apt-get update && \
|
||||
apt-get install -y --no-install-recommends cri-o=1.18.3~2
|
||||
apt-get install -y --no-install-recommends cri-o=1.18.3~3
|
||||
|
||||
# install podman
|
||||
RUN sh -c "echo 'deb https://dl.bintray.com/afbjorklund/podman focal main' > /etc/apt/sources.list.d/podman.list" && \
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
[
|
||||
{
|
||||
"name": "v1.12.3",
|
||||
"checksums": {
|
||||
"darwin": "060275cd2129fbf3ce38f245a85651a6f050dff25a3ed0454241e1319ea1ab08",
|
||||
"linux": "664ebef01166ef6c6b13ff1d70faecca9292e2fcdc85766e8ebd2c607488711c",
|
||||
"windows": "994e7a232c57b6b917c20ad2e40e88a6b8e80e057212b14def3307e4b22ebbe6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1.12.2",
|
||||
"checksums": {
|
||||
|
|
1
go.mod
1
go.mod
|
@ -72,6 +72,7 @@ require (
|
|||
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
|
||||
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121
|
||||
|
|
|
@ -227,30 +227,39 @@ type podmanSysInfo struct {
|
|||
} `json:"store"`
|
||||
}
|
||||
|
||||
var dockerInfoGetter = func() (string, error) {
|
||||
rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
|
||||
return rr.Stdout.String(), err
|
||||
}
|
||||
|
||||
// dockerSystemInfo returns docker system info --format '{{json .}}'
|
||||
func dockerSystemInfo() (dockerSysInfo, error) {
|
||||
var ds dockerSysInfo
|
||||
rr, err := runCmd(exec.Command(Docker, "system", "info", "--format", "{{json .}}"))
|
||||
rawJSON, err := dockerInfoGetter()
|
||||
if err != nil {
|
||||
return ds, errors.Wrap(err, "get docker system info")
|
||||
return ds, errors.Wrap(err, "docker system info")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ds); err != nil {
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ds); err != nil {
|
||||
return ds, errors.Wrapf(err, "unmarshal docker system info")
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
var podmanInfoGetter = func() (string, error) {
|
||||
rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
|
||||
return rr.Stdout.String(), err
|
||||
}
|
||||
|
||||
// podmanSysInfo returns podman system info --format '{{json .}}'
|
||||
func podmanSystemInfo() (podmanSysInfo, error) {
|
||||
var ps podmanSysInfo
|
||||
rr, err := runCmd(exec.Command(Podman, "system", "info", "--format", "json"))
|
||||
rawJSON, err := podmanInfoGetter()
|
||||
if err != nil {
|
||||
return ps, errors.Wrap(err, "get podman system info")
|
||||
return ps, errors.Wrap(err, "podman system info")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(rr.Stdout.String())), &ps); err != nil {
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ps); err != nil {
|
||||
return ps, errors.Wrapf(err, "unmarshal podman system info")
|
||||
}
|
||||
return ps, nil
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
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 oci
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var daemonResponseMock string
|
||||
var daemonInfoGetterMock = func() (string, error) {
|
||||
return daemonResponseMock, nil
|
||||
}
|
||||
|
||||
func TestDockerSystemInfo(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string // test case bane
|
||||
OciBin string // Docker or Podman
|
||||
RawJSON string // raw response from json
|
||||
ShouldError bool
|
||||
CPUs int
|
||||
Memory int64
|
||||
OS string
|
||||
}{
|
||||
{
|
||||
Name: "linux_docker",
|
||||
OciBin: "docker",
|
||||
RawJSON: `{"ID":"7PYP:53DU:MLWX:EDQG:YG2Y:UJLB:J7SD:4SAI:XF2Y:N2MR:MU53:DR3N","Containers":3,"ContainersRunning":1,"ContainersPaused":0,"ContainersStopped":2,"Images":76,"Driver":"overlay2","DriverStatus":[["Backing Filesystem","extfs"],["Supports d_type","true"],["Native Overlay Diff","true"]],"SystemStatus":null,"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","local","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":false,"KernelMemory":true,"KernelMemoryTCP":false,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":false,"NFd":27,"OomKillDisable":true,"NGoroutines":48,"SystemTime":"2020-08-11T18:16:17.494440681Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.9.0-8-amd64","OperatingSystem":"Debian GNU/Linux 9 (stretch)","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":[],"AllowNondistributableArtifactsHostnames":[],"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":[],"Secure":true,"Official":true}},"Mirrors":[]},"NCPU":16,"MemTotal":63336071168,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"image-builder-cloud-shell-v20200811-102837","Labels":[],"ExperimentalBuild":false,"ServerVersion":"18.09.0","ClusterStore":"","ClusterAdvertise":"","Runtimes":{"runc":{"path":"runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"7ad184331fa3e55e52b890ea95e65ba581ae3429","Expected":"7ad184331fa3e55e52b890ea95e65ba581ae3429"},"RuncCommit":{"ID":"dc9208a3303feef5b3839f4323d9beb36df0a9dd","Expected":"dc9208a3303feef5b3839f4323d9beb36df0a9dd"},"InitCommit":{"ID":"fec3683","Expected":"fec3683"},"SecurityOptions":["name=seccomp,profile=default"],"ProductLicense":"Community Engine","Warnings":["WARNING: No swap limit support"],"ClientInfo":{"Debug":false,"Plugins":[],"Warnings":null}}`,
|
||||
ShouldError: false,
|
||||
CPUs: 16,
|
||||
Memory: 63336071168,
|
||||
OS: "linux",
|
||||
},
|
||||
{
|
||||
Name: "macos_docker",
|
||||
OciBin: "docker",
|
||||
RawJSON: `{"ID":"T54Z:I56K:XRG5:BTMK:BI72:IMI3:QBBF:H2PD:DGAF:EQLJ:7JFZ:PF54","Containers":5,"ContainersRunning":1,"ContainersPaused":0,"ContainersStopped":4,"Images":84,"Driver":"overlay2","DriverStatus":[["Backing Filesystem","extfs"],["Supports d_type","true"],["Native Overlay Diff","true"]],"SystemStatus":null,"Plugins":{"Volume":["local"],"Network":["bridge","host","ipvlan","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","local","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"KernelMemoryTCP":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":true,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":46,"OomKillDisable":true,"NGoroutines":56,"SystemTime":"2020-08-11T19:33:23.8936297Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":3,"KernelVersion":"4.19.76-linuxkit","OperatingSystem":"Docker Desktop","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":[],"AllowNondistributableArtifactsHostnames":[],"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":[],"Secure":true,"Official":true}},"Mirrors":[]},"NCPU":4,"MemTotal":3142250496,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"gateway.docker.internal:3128","HttpsProxy":"gateway.docker.internal:3129","NoProxy":"","Name":"docker-desktop","Labels":[],"ExperimentalBuild":false,"ServerVersion":"19.03.12","ClusterStore":"","ClusterAdvertise":"","Runtimes":{"runc":{"path":"runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"7ad184331fa3e55e52b890ea95e65ba581ae3429","Expected":"7ad184331fa3e55e52b890ea95e65ba581ae3429"},"RuncCommit":{"ID":"dc9208a3303feef5b3839f4323d9beb36df0a9dd","Expected":"dc9208a3303feef5b3839f4323d9beb36df0a9dd"},"InitCommit":{"ID":"fec3683","Expected":"fec3683"},"SecurityOptions":["name=seccomp,profile=default"],"ProductLicense":"Community Engine","Warnings":null,"ClientInfo":{"Debug":false,"Plugins":[],"Warnings":null}}
|
||||
`,
|
||||
ShouldError: false,
|
||||
CPUs: 4,
|
||||
Memory: 3142250496,
|
||||
OS: "linux",
|
||||
},
|
||||
{
|
||||
Name: "windows_docker",
|
||||
OciBin: "docker",
|
||||
RawJSON: `{"ID":"CVVH:7ZIB:S5EO:L6VO:MGZ3:TRLS:JGIS:4ZI2:27Z7:MQAQ:YSLT:HEHB","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":3,"Driver":"overlay2","DriverStatus":[["Backing Filesystem","extfs"],["Supports d_type","true"],["Native Overlay Diff","true"]],"SystemStatus":null,"Plugins":{"Volume":["local"],"Network":["bridge","host","ipvlan","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","local","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"KernelMemoryTCP":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":true,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":35,"OomKillDisable":true,"NGoroutines":45,"SystemTime":"2020-08-11T19:39:26.083212722Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":1,"KernelVersion":"4.19.76-linuxkit","OperatingSystem":"Docker Desktop","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":[],"AllowNondistributableArtifactsHostnames":[],"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":[],"Secure":true,"Official":true}},"Mirrors":[]},"NCPU":4,"MemTotal":10454695936,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"docker-desktop","Labels":[],"ExperimentalBuild":false,"ServerVersion":"19.03.12","ClusterStore":"","ClusterAdvertise":"","Runtimes":{"runc":{"path":"runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"7ad184331fa3e55e52b890ea95e65ba581ae3429","Expected":"7ad184331fa3e55e52b890ea95e65ba581ae3429"},"RuncCommit":{"ID":"dc9208a3303feef5b3839f4323d9beb36df0a9dd","Expected":"dc9208a3303feef5b3839f4323d9beb36df0a9dd"},"InitCommit":{"ID":"fec3683","Expected":"fec3683"},"SecurityOptions":["name=seccomp,profile=default"],"ProductLicense":"Community Engine","Warnings":null,"ClientInfo":{"Debug":false,"Plugins":[],"Warnings":null}}
|
||||
`,
|
||||
ShouldError: false,
|
||||
CPUs: 4,
|
||||
Memory: 10454695936,
|
||||
OS: "linux",
|
||||
}, {
|
||||
Name: "podman_1.8_linux",
|
||||
OciBin: "podman",
|
||||
RawJSON: `{
|
||||
"host": {
|
||||
"BuildahVersion": "1.13.1",
|
||||
"CgroupVersion": "v1",
|
||||
"Conmon": {
|
||||
"package": "conmon: /usr/libexec/podman/conmon",
|
||||
"path": "/usr/libexec/podman/conmon",
|
||||
"version": "conmon version 2.0.10, commit: unknown"
|
||||
},
|
||||
"Distribution": {
|
||||
"distribution": "debian",
|
||||
"version": "10"
|
||||
},
|
||||
"MemFree": 4907147264,
|
||||
"MemTotal": 7839653888,
|
||||
"OCIRuntime": {
|
||||
"name": "runc",
|
||||
"package": "runc: /usr/sbin/runc",
|
||||
"path": "/usr/sbin/runc",
|
||||
"version": "runc version 1.0.0~rc6+dfsg1\ncommit: 1.0.0~rc6+dfsg1-3 spec: 1.0.1"
|
||||
},
|
||||
"SwapFree": 0,
|
||||
"SwapTotal": 0,
|
||||
"arch": "amd64",
|
||||
"cpus": 2,
|
||||
"eventlogger": "journald",
|
||||
"hostname": "podman-exp-temp",
|
||||
"kernel": "4.19.0-8-cloud-amd64",
|
||||
"os": "linux",
|
||||
"rootless": false,
|
||||
"uptime": "2690h 47m 23.31s (Approximately 112.08 days)"
|
||||
},
|
||||
"registries": {
|
||||
"search": [
|
||||
"docker.io",
|
||||
"quay.io"
|
||||
]
|
||||
},
|
||||
"store": {
|
||||
"ConfigFile": "/etc/containers/storage.conf",
|
||||
"ContainerStore": {
|
||||
"number": 1
|
||||
},
|
||||
"GraphDriverName": "overlay",
|
||||
"GraphOptions": {},
|
||||
"GraphRoot": "/var/lib/containers/storage",
|
||||
"GraphStatus": {
|
||||
"Backing Filesystem": "extfs",
|
||||
"Native Overlay Diff": "true",
|
||||
"Supports d_type": "true",
|
||||
"Using metacopy": "false"
|
||||
},
|
||||
"ImageStore": {
|
||||
"number": 2
|
||||
},
|
||||
"RunRoot": "/var/run/containers/storage",
|
||||
"VolumePath": "/var/lib/containers/storage/volumes"
|
||||
}
|
||||
}
|
||||
`, CPUs: 2,
|
||||
Memory: 7839653888,
|
||||
OS: "linux"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
daemonResponseMock = tc.RawJSON
|
||||
// setting up mock funcs
|
||||
dockerInfoGetter = daemonInfoGetterMock
|
||||
podmanInfoGetter = daemonInfoGetterMock
|
||||
s, err := DaemonInfo(tc.OciBin)
|
||||
|
||||
if err != nil && !tc.ShouldError {
|
||||
t.Errorf("Expected not to have error but got %v", err)
|
||||
}
|
||||
if s.CPUs != tc.CPUs {
|
||||
t.Errorf("Expected CPUs to be %d but got %d", tc.CPUs, s.CPUs)
|
||||
}
|
||||
if s.TotalMemory != tc.Memory {
|
||||
t.Errorf("Expected Memory to be %d but got %d", tc.Memory, s.TotalMemory)
|
||||
}
|
||||
if s.OSType != tc.OS {
|
||||
t.Errorf("Expected OS type to be %q but got %q", tc.OS, s.OSType)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||
|
@ -30,6 +31,9 @@ func ControlPlaneEndpoint(cc *config.ClusterConfig, cp *config.Node, driverName
|
|||
port, err := oci.ForwardedPort(cc.Driver, cc.Name, cp.Port)
|
||||
hostname := oci.DefaultBindIPV4
|
||||
ip := net.ParseIP(hostname)
|
||||
if ip == nil {
|
||||
return hostname, ip, port, fmt.Errorf("failed to parse ip for %q", hostname)
|
||||
}
|
||||
|
||||
// https://github.com/kubernetes/minikube/issues/3878
|
||||
if cc.KubernetesConfig.APIServerName != constants.APIServerName {
|
||||
|
@ -43,5 +47,9 @@ func ControlPlaneEndpoint(cc *config.ClusterConfig, cp *config.Node, driverName
|
|||
if cc.KubernetesConfig.APIServerName != constants.APIServerName {
|
||||
hostname = cc.KubernetesConfig.APIServerName
|
||||
}
|
||||
return hostname, net.ParseIP(cp.IP), cp.Port, nil
|
||||
ip := net.ParseIP(cp.IP)
|
||||
if ip == nil {
|
||||
return hostname, ip, cp.Port, fmt.Errorf("failed to parse ip for %q", cp.IP)
|
||||
}
|
||||
return hostname, ip, cp.Port, nil
|
||||
}
|
||||
|
|
|
@ -44,6 +44,9 @@ func cmdOut(args ...string) (string, error) {
|
|||
err := cmd.Run()
|
||||
glog.Infof("[stdout =====>] : %s", stdout.String())
|
||||
glog.Infof("[stderr =====>] : %s", stderr.String())
|
||||
if err != nil {
|
||||
glog.Infof("[err =====>] : %v", err)
|
||||
}
|
||||
return stdout.String(), err
|
||||
}
|
||||
|
||||
|
|
|
@ -76,11 +76,11 @@ After job completion, click "Console Output" to verify that the release complete
|
|||
|
||||
**Note: If you are releasing a beta, you are done when you get here.**
|
||||
|
||||
## Check releases.json
|
||||
## Merge the releases.json change
|
||||
|
||||
This file is used for auto-update notifications, but is not active until releases.json is copied to GCS.
|
||||
The release script updates https://storage.googleapis.com/minikube/releases.json - which is used by the minikube binary to check for updates, and is live immediately.
|
||||
|
||||
minikube-bot will send out a PR to update the release checksums at the top of `deploy/minikube/releases.json`. You should merge this PR.
|
||||
minikube-bot will also send out a PR to merge this into the tree. Please merge this PR to keep GCS and Github in sync.
|
||||
|
||||
## Package managers which include minikube
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ This is an experimental driver. Please use it only for experimental reasons unti
|
|||
|
||||
## Usage
|
||||
|
||||
It's recommended to run minikube with the podman driver and [CRI-O container runtime](https://https://cri-o.io/):
|
||||
It's recommended to run minikube with the podman driver and [CRI-O container runtime](https://cri-o.io/):
|
||||
|
||||
```shell
|
||||
minikube start --driver=podman --container-runtime=cri-o
|
||||
|
|
|
@ -165,7 +165,10 @@ func TestDownloadOnlyKic(t *testing.T) {
|
|||
args := []string{"start", "--download-only", "-p", profile, "--force", "--alsologtostderr"}
|
||||
args = append(args, StartArgs()...)
|
||||
|
||||
if _, err := Run(t, exec.CommandContext(ctx, Target(), args...)); err != nil {
|
||||
cmd := exec.CommandContext(ctx, Target(), args...)
|
||||
// make sure this works even if docker daemon isn't running
|
||||
cmd.Env = append(os.Environ(), "DOCKER_HOST=/does/not/exist")
|
||||
if _, err := Run(t, cmd); err != nil {
|
||||
t.Errorf("start with download only failed %q : %v", args, err)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue