diff --git a/Makefile b/Makefile index 661a60ffc3..f6d00b7ca5 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,7 @@ STORAGE_PROVISIONER_MANIFEST ?= $(REGISTRY)/storage-provisioner:$(STORAGE_PROVIS STORAGE_PROVISIONER_IMAGE ?= $(REGISTRY)/storage-provisioner-$(GOARCH):$(STORAGE_PROVISIONER_TAG) # Set the version information for the Kubernetes servers -MINIKUBE_LDFLAGS := -X k8s.io/minikube/pkg/version.version=$(VERSION) -X k8s.io/minikube/pkg/version.isoVersion=$(ISO_VERSION) -X k8s.io/minikube/pkg/version.isoPath=$(ISO_BUCKET) -X k8s.io/minikube/pkg/version.gitCommitID=$(COMMIT) -X k8s.io/minikube/pkg/version.storageProvisionerVersion=$(STORAGE_PROVISIONER_TAG) +MINIKUBE_LDFLAGS := -X k8s.io/minikube/pkg/version.version=$(VERSION) -X k8s.io/minikube/pkg/version.isoVersion=$(ISO_VERSION) -X k8s.io/minikube/pkg/version.gitCommitID=$(COMMIT) -X k8s.io/minikube/pkg/version.storageProvisionerVersion=$(STORAGE_PROVISIONER_TAG) PROVISIONER_LDFLAGS := "-X k8s.io/minikube/pkg/storage.version=$(STORAGE_PROVISIONER_TAG) -s -w -extldflags '-static'" MINIKUBEFILES := ./cmd/minikube/ diff --git a/cmd/minikube/cmd/cache.go b/cmd/minikube/cmd/cache.go index ff1ab11568..7933f4f7ec 100644 --- a/cmd/minikube/cmd/cache.go +++ b/cmd/minikube/cmd/cache.go @@ -18,17 +18,25 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" + "k8s.io/klog/v2" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" + "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/image" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/node" + "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" ) // cacheImageConfigKey is the config field name used to store which images we have previously cached const cacheImageConfigKey = "cache" +var ( + all string +) + // cacheCmd represents the cache command var cacheCmd = &cobra.Command{ Use: "cache", @@ -42,8 +50,9 @@ var addCacheCmd = &cobra.Command{ Short: "Add an image to local cache.", Long: "Add an image to local cache.", Run: func(cmd *cobra.Command, args []string) { + out.WarningT("\"minikube cache\" will be deprecated in upcoming versions, please switch to \"minikube image load\"") // Cache and load images into docker daemon - if err := machine.CacheAndLoadImages(args); err != nil { + if err := machine.CacheAndLoadImages(args, cacheAddProfiles()); err != nil { exit.Error(reason.InternalCacheLoad, "Failed to cache and load images", err) } // Add images to config file @@ -53,6 +62,26 @@ var addCacheCmd = &cobra.Command{ }, } +func addCacheCmdFlags() { + addCacheCmd.Flags().Bool(all, false, "Add image to cache for all running minikube clusters") +} + +func cacheAddProfiles() []*config.Profile { + if viper.GetBool(all) { + validProfiles, _, err := config.ListProfiles() // need to load image to all profiles + if err != nil { + klog.Warningf("error listing profiles: %v", err) + } + return validProfiles + } + profile := viper.GetString(config.ProfileName) + p, err := config.LoadProfile(profile) + if err != nil { + exit.Message(reason.Usage, "{{.profile}} profile is not valid: {{.err}}", out.V{"profile": profile, "err": err}) + } + return []*config.Profile{p} +} + // deleteCacheCmd represents the cache delete command var deleteCacheCmd = &cobra.Command{ Use: "delete", @@ -76,7 +105,7 @@ var reloadCacheCmd = &cobra.Command{ Short: "reload cached images.", Long: "reloads images previously added using the 'cache add' subcommand", Run: func(cmd *cobra.Command, args []string) { - err := node.CacheAndLoadImagesInConfig() + err := node.CacheAndLoadImagesInConfig(cacheAddProfiles()) if err != nil { exit.Error(reason.GuestCacheLoad, "Failed to reload cached images", err) } @@ -84,6 +113,7 @@ var reloadCacheCmd = &cobra.Command{ } func init() { + addCacheCmdFlags() cacheCmd.AddCommand(addCacheCmd) cacheCmd.AddCommand(deleteCacheCmd) cacheCmd.AddCommand(reloadCacheCmd) diff --git a/cmd/minikube/cmd/image.go b/cmd/minikube/cmd/image.go new file mode 100644 index 0000000000..3186c7120a --- /dev/null +++ b/cmd/minikube/cmd/image.go @@ -0,0 +1,58 @@ +/* +Copyright 2017 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/exit" + "k8s.io/minikube/pkg/minikube/machine" + "k8s.io/minikube/pkg/minikube/reason" +) + +// imageCmd represents the image command +var imageCmd = &cobra.Command{ + Use: "image", + Short: "Load a local image into minikube", + Long: "Load a local image into minikube", +} + +// loadImageCmd represents the image load command +var loadImageCmd = &cobra.Command{ + Use: "load", + Short: "Load a local image into minikube", + Long: "Load a local image into minikube", + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + exit.Message(reason.Usage, "Please provide an image in your local daemon to load into minikube via ") + } + // Cache and load images into docker daemon + profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) + if err != nil { + exit.Error(reason.Usage, "loading profile", err) + } + img := args[0] + if err := machine.CacheAndLoadImages([]string{img}, []*config.Profile{profile}); err != nil { + exit.Error(reason.GuestImageLoad, "Failed to load image", err) + } + }, +} + +func init() { + imageCmd.AddCommand(loadImageCmd) +} diff --git a/cmd/minikube/cmd/root.go b/cmd/minikube/cmd/root.go index 8b03ab5086..590e523d60 100644 --- a/cmd/minikube/cmd/root.go +++ b/cmd/minikube/cmd/root.go @@ -217,6 +217,7 @@ func init() { dockerEnvCmd, podmanEnvCmd, cacheCmd, + imageCmd, }, }, { diff --git a/deploy/addons/gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl b/deploy/addons/gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl index 149a84a788..6ab76171ef 100644 --- a/deploy/addons/gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl +++ b/deploy/addons/gcp-auth/gcp-auth-webhook.yaml.tmpl.tmpl @@ -41,7 +41,7 @@ rules: - update --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: minikube-gcp-auth-certs diff --git a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash index 7d1aa5a788..5c7a38a172 100644 --- a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash +++ b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.hash @@ -26,3 +26,4 @@ sha256 9f1ec28e357a8f18e9561129239caf9c0807d74756e21cc63637c7fdeaafe847 docker- sha256 02936a3585f12f13b21b95e02ae722d74eaf1870b536997e914659ee307b2ac4 docker-20.10.0.tgz sha256 8790f3b94ee07ca69a9fdbd1310cbffc729af0a07e5bf9f34a79df1e13d2e50e docker-20.10.1.tgz sha256 97017e32a8ecbdd1826bb3c7b1424303ee0dea3f900d33591b1df5e394ed4eed docker-20.10.2.tgz +sha256 47065a47f0692cd5af03073c7386fe090d9ef5ac88a7d8455a884d8e15809be5 docker-20.10.3.tgz diff --git a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk index db38e6a105..05383d9fc7 100644 --- a/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk +++ b/deploy/iso/minikube-iso/package/docker-bin/docker-bin.mk @@ -4,7 +4,7 @@ # ################################################################################ -DOCKER_BIN_VERSION = 20.10.2 +DOCKER_BIN_VERSION = 20.10.3 DOCKER_BIN_SITE = https://download.docker.com/linux/static/stable/x86_64 DOCKER_BIN_SOURCE = docker-$(DOCKER_BIN_VERSION).tgz diff --git a/deploy/kicbase/Dockerfile b/deploy/kicbase/Dockerfile index 77ca503aaf..3c7ebecd02 100644 --- a/deploy/kicbase/Dockerfile +++ b/deploy/kicbase/Dockerfile @@ -127,7 +127,7 @@ RUN sh -c "echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/li clean-install containers-common catatonit conmon containernetworking-plugins cri-tools podman-plugins # install cri-o based on https://github.com/cri-o/cri-o/blob/release-1.19/README.md#installing-cri-o -RUN sh -c "echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.19/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.18.list" && \ +RUN sh -c "echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.19/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.19.list" && \ curl -LO https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.19/xUbuntu_20.04/Release.key && \ apt-key add - < Release.key && \ clean-install cri-o cri-o-runc diff --git a/go.mod b/go.mod index 11eb8cead4..529a3ccf1e 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/docker/cli v0.0.0-20200303162255-7d407207c304 // indirect github.com/docker/docker v17.12.0-ce-rc1.0.20181225093023-5ddb1d410a8b+incompatible github.com/docker/go-units v0.4.0 - github.com/docker/machine v0.16.2 // v0.16.2^ + github.com/docker/machine v0.16.2 github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect github.com/evanphx/json-patch v4.5.0+incompatible // indirect @@ -39,6 +39,7 @@ require ( github.com/googleapis/gnostic v0.3.0 // indirect github.com/hashicorp/go-getter v1.5.1 github.com/hashicorp/go-retryablehttp v0.6.6 + github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 // indirect github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect github.com/hooklift/iso9660 v0.0.0-20170318115843-1cf07e5970d8 github.com/intel-go/cpuid v0.0.0-20181003105527-1a4a6f06a1c6 // indirect @@ -104,8 +105,8 @@ require ( replace ( git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999 - github.com/briandowns/spinner => github.com/alonyb/spinner v1.12.1 - github.com/docker/machine => github.com/machine-drivers/machine v0.7.1-0.20200810185219-7d42fed1b770 + github.com/briandowns/spinner => github.com/alonyb/spinner v1.12.6 + github.com/docker/machine => github.com/machine-drivers/machine v0.7.1-0.20200824110434-7da9b61f0a42 github.com/google/go-containerregistry => github.com/afbjorklund/go-containerregistry v0.1.2-0.20210101161202-de47504a564f github.com/samalba/dockerclient => github.com/sayboras/dockerclient v1.0.0 k8s.io/api => k8s.io/api v0.17.3 diff --git a/go.sum b/go.sum index 10bb2652b8..b74a53b1f1 100644 --- a/go.sum +++ b/go.sum @@ -109,8 +109,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alonyb/spinner v1.12.1 h1:zB6IQ29/kTR/NWHJhIgU2tXW+fhXa3K5zrDQMddd9H0= -github.com/alonyb/spinner v1.12.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= +github.com/alonyb/spinner v1.12.6 h1:mA00RZknbJVQsvIbbLIspcXNVriiOeY6OZPsmlozy7k= +github.com/alonyb/spinner v1.12.6/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -517,6 +517,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ= +github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E= github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 h1:WgfvpuKg42WVLkxNwzfFraXkTXPK36bMqXvMFN67clI= @@ -611,8 +613,8 @@ github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H7 github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/machine-drivers/docker-machine-driver-vmware v0.1.1 h1:+E1IKKk+6kaQrCPg6edJZ/zISZijuZTPnzy6RE4C/Ho= github.com/machine-drivers/docker-machine-driver-vmware v0.1.1/go.mod h1:ej014C83EmSnxJeJ8PtVb8OLJ91PJKO1Q8Y7sM5CK0o= -github.com/machine-drivers/machine v0.7.1-0.20200810185219-7d42fed1b770 h1:jc5SzpD28ZqDb+PoA4FxOwkl+slv593qJjrMVM35JFQ= -github.com/machine-drivers/machine v0.7.1-0.20200810185219-7d42fed1b770/go.mod h1:79Uwa2hGd5S39LDJt58s8JZcIhGEK6pkq9bsuTbFWbk= +github.com/machine-drivers/machine v0.7.1-0.20200824110434-7da9b61f0a42 h1:poqKURqws9SLrsrxwMEvQiIiqyO9GDZDnhWKkgEX/7M= +github.com/machine-drivers/machine v0.7.1-0.20200824110434-7da9b61f0a42/go.mod h1:79Uwa2hGd5S39LDJt58s8JZcIhGEK6pkq9bsuTbFWbk= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -1079,6 +1081,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/hack/jenkins/linux_integration_tests_docker_containerd.sh b/hack/jenkins/linux_integration_tests_docker_containerd.sh old mode 100644 new mode 100755 diff --git a/hack/jenkins/linux_integration_tests_docker_crio.sh b/hack/jenkins/linux_integration_tests_docker_crio.sh new file mode 100755 index 0000000000..f7c2aad413 --- /dev/null +++ b/hack/jenkins/linux_integration_tests_docker_crio.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This script runs the integration tests on a Linux machine for the KVM Driver + +# The script expects the following env variables: +# MINIKUBE_LOCATION: GIT_COMMIT from upstream build. +# COMMIT: Actual commit ID from upstream build +# EXTRA_BUILD_ARGS (optional): Extra args to be passed into the minikube integrations tests +# access_token: The Github API access token. Injected by the Jenkins credential provider. + +set -e + +OS_ARCH="linux-amd64" +VM_DRIVER="docker" +JOB_NAME="Docker_Linux_crio" +CONTAINER_RUNTIME="crio" + + + +mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES" +sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP" + +# removing possible left over docker containers from previous runs +docker rm -f -v $(docker ps -aq) >/dev/null 2>&1 || true + +source ./common.sh diff --git a/hack/jenkins/linux_integration_tests_kvm_containerd.sh b/hack/jenkins/linux_integration_tests_kvm_containerd.sh new file mode 100755 index 0000000000..61656887f4 --- /dev/null +++ b/hack/jenkins/linux_integration_tests_kvm_containerd.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This script runs the integration tests on a Linux machine for the KVM Driver + +# The script expects the following env variables: +# MINIKUBE_LOCATION: GIT_COMMIT from upstream build. +# COMMIT: Actual commit ID from upstream build +# EXTRA_BUILD_ARGS (optional): Extra args to be passed into the minikube integrations tests +# access_token: The Github API access token. Injected by the Jenkins credential provider. + +set -e + +OS_ARCH="linux-amd64" +VM_DRIVER="kvm2" +JOB_NAME="KVM_Linux_containerd" +CONTAINER_RUNTIME="containerd" + + + +mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES" +sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP" + +sudo apt-get update +sudo apt-get -y install qemu-system libvirt-clients libvirt-daemon-system ebtables iptables dnsmasq +sudo adduser jenkins libvirt || true + +source ./common.sh diff --git a/hack/jenkins/linux_integration_tests_kvm_crio.sh b/hack/jenkins/linux_integration_tests_kvm_crio.sh new file mode 100755 index 0000000000..1a57de6f18 --- /dev/null +++ b/hack/jenkins/linux_integration_tests_kvm_crio.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This script runs the integration tests on a Linux machine for the KVM Driver + +# The script expects the following env variables: +# MINIKUBE_LOCATION: GIT_COMMIT from upstream build. +# COMMIT: Actual commit ID from upstream build +# EXTRA_BUILD_ARGS (optional): Extra args to be passed into the minikube integrations tests +# access_token: The Github API access token. Injected by the Jenkins credential provider. + +set -e + +OS_ARCH="linux-amd64" +VM_DRIVER="kvm2" +JOB_NAME="KVM_Linux_crio" +CONTAINER_RUNTIME="crio" + + + +mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES" +sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP" + +sudo apt-get update +sudo apt-get -y install qemu-system libvirt-clients libvirt-daemon-system ebtables iptables dnsmasq +sudo adduser jenkins libvirt || true + +source ./common.sh diff --git a/hack/jenkins/minikube_set_pending.sh b/hack/jenkins/minikube_set_pending.sh index 20f2b5f743..63c50dd603 100755 --- a/hack/jenkins/minikube_set_pending.sh +++ b/hack/jenkins/minikube_set_pending.sh @@ -32,16 +32,19 @@ if [ "${ghprbPullId}" == "master" ]; then fi jobs=( - 'HyperKit_Functional_macOS' + # 'HyperKit_Functional_macOS' 'Hyper-V_Windows' 'VirtualBox_Linux' # 'VirtualBox_macOS' 'VirtualBox_Windows' # 'KVM-GPU_Linux' - Disabled 'KVM_Linux' + 'KVM_Linux_containerd' + 'KVM_Linux_crio' 'none_Linux' 'Docker_Linux' 'Docker_Linux_containerd' + 'Docker_Linux_crio' # 'Docker_macOS' 'Docker_Windows' # 'Podman_Linux' diff --git a/pkg/drivers/ssh/ssh.go b/pkg/drivers/ssh/ssh.go index d36fd8b073..d2e502aeb6 100644 --- a/pkg/drivers/ssh/ssh.go +++ b/pkg/drivers/ssh/ssh.go @@ -85,18 +85,22 @@ func (d *Driver) DriverName() string { return "ssh" } +// GetSSHHostname returns hostname for use with ssh func (d *Driver) GetSSHHostname() (string, error) { return d.GetIP() } +// GetSSHUsername returns username for use with ssh func (d *Driver) GetSSHUsername() string { return d.SSHUser } +// GetSSHKeyPath returns the key path for SSH func (d *Driver) GetSSHKeyPath() string { return d.SSHKeyPath } +// PreCreateCheck checks for correct privileges and dependencies func (d *Driver) PreCreateCheck() error { if d.SSHKey != "" { if _, err := os.Stat(d.SSHKey); os.IsNotExist(err) { @@ -107,6 +111,7 @@ func (d *Driver) PreCreateCheck() error { return nil } +// Create a host using the driver's config func (d *Driver) Create() error { if d.SSHKey == "" { log.Info("No SSH key specified. Assuming an existing key at the default location.") @@ -134,6 +139,7 @@ func (d *Driver) Create() error { return nil } +// GetURL returns a Docker URL inside this host func (d *Driver) GetURL() (string, error) { if err := drivers.MustBeRunning(d); err != nil { return "", err @@ -147,6 +153,7 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s", net.JoinHostPort(ip, strconv.Itoa(d.EnginePort))), nil } +// GetState returns the state that the host is in (running, stopped, etc) func (d *Driver) GetState() (state.State, error) { address := net.JoinHostPort(d.IPAddress, strconv.Itoa(d.SSHPort)) @@ -224,6 +231,7 @@ func (d *Driver) Kill() error { return nil } +// Remove a host, including any data which may have been written by it. func (d *Driver) Remove() error { return nil } diff --git a/pkg/minikube/assets/addons.go b/pkg/minikube/assets/addons.go index a0aae92486..4b4db916ab 100644 --- a/pkg/minikube/assets/addons.go +++ b/pkg/minikube/assets/addons.go @@ -486,7 +486,7 @@ var Addons = map[string]*Addon{ "0640"), }, false, "gcp-auth", map[string]string{ "KubeWebhookCertgen": "jettech/kube-webhook-certgen:v1.3.0", - "GCPAuthWebhook": "k8s-minikube/gcp-auth-webhook:v0.0.3", + "GCPAuthWebhook": "k8s-minikube/gcp-auth-webhook:v0.0.4", }, map[string]string{ "GCPAuthWebhook": "gcr.io", }), diff --git a/pkg/minikube/bootstrapper/bsutil/ktmpl/kubelet.go b/pkg/minikube/bootstrapper/bsutil/ktmpl/kubelet.go index 04c7c779c7..3c6f7fffda 100644 --- a/pkg/minikube/bootstrapper/bsutil/ktmpl/kubelet.go +++ b/pkg/minikube/bootstrapper/bsutil/ktmpl/kubelet.go @@ -33,11 +33,11 @@ ExecStart={{.KubeletPath}}{{if .ExtraOptions}} {{.ExtraOptions}}{{end}} var KubeletServiceTemplate = template.Must(template.New("kubeletServiceTemplate").Parse(`[Unit] Description=kubelet: The Kubernetes Node Agent Documentation=http://kubernetes.io/docs/ +StartLimitIntervalSec=0 [Service] ExecStart={{.KubeletPath}} Restart=always -StartLimitInterval=0 # Tuned for local dev: faster than upstream default (10s), but slower than systemd default (100ms) RestartSec=600ms diff --git a/pkg/minikube/bootstrapper/bsutil/kverify/kverify.go b/pkg/minikube/bootstrapper/bsutil/kverify/kverify.go index 76a976e36a..3a1bb182da 100644 --- a/pkg/minikube/bootstrapper/bsutil/kverify/kverify.go +++ b/pkg/minikube/bootstrapper/bsutil/kverify/kverify.go @@ -35,7 +35,7 @@ const ( AppsRunningKey = "apps_running" // NodeReadyKey is the name used in the flags for waiting for the node status to be ready NodeReadyKey = "node_ready" - // NodeReadyKey is the name used in the flags for waiting for the node status to be ready + // KubeletKey is the name used in the flags for waiting for the kubelet status to be ready KubeletKey = "kubelet" ) diff --git a/pkg/minikube/cni/cni.go b/pkg/minikube/cni/cni.go index c0d2a44b25..46e738a14d 100644 --- a/pkg/minikube/cni/cni.go +++ b/pkg/minikube/cni/cni.go @@ -93,6 +93,7 @@ func New(cc config.ClusterConfig) (Manager, error) { } } +// IsDisabled checks if CNI is disabled func IsDisabled(cc config.ClusterConfig) bool { if cc.KubernetesConfig.NetworkPlugin != "" && cc.KubernetesConfig.NetworkPlugin != "cni" { return true diff --git a/pkg/minikube/command/kic_runner.go b/pkg/minikube/command/kic_runner.go index 8f4a682618..3f679d762f 100644 --- a/pkg/minikube/command/kic_runner.go +++ b/pkg/minikube/command/kic_runner.go @@ -186,17 +186,13 @@ func (k *kicRunner) Copy(f assets.CopyableFile) error { } } klog.Infof("%s (temp): %s --> %s (%d bytes)", k.ociBin, src, dst, f.GetLength()) - tmpFolder := "" - // Snap only allows an application to see its own files in /tmp, making Docker unable to copy memory assets - // https://github.com/kubernetes/minikube/issues/10020 - if isSnapBinary() { - home, err := os.UserHomeDir() - if err != nil { - return errors.Wrap(err, "detecting home dir") - } - tmpFolder = home + isSnap := isSnapBinary() + tmpFolder, err := tempDirectory(isSnap) + if err != nil { + return errors.Wrap(err, "determining temp directory") } + tf, err := ioutil.TempFile(tmpFolder, "tmpf-memory-asset") if err != nil { return errors.Wrap(err, "creating temporary file") @@ -209,6 +205,24 @@ func (k *kicRunner) Copy(f assets.CopyableFile) error { return k.copy(tf.Name(), dst) } +// tempDirectory returns the directory to use as the temp directory +// or an empty string if it should use the os default temp directory. +func tempDirectory(isSnap bool) (string, error) { + if !isSnap { + return "", nil + } + + // Snap only allows an application to see its own files in /tmp, making Docker unable to copy memory assets + // https://github.com/kubernetes/minikube/issues/10020 + + home, err := os.UserHomeDir() + if err != nil { + return "", errors.Wrap(err, "detecting home dir") + } + return home, nil +} + +// isSnapBinary returns true if the binary path includes "snap". func isSnapBinary() bool { ex, err := os.Executable() if err != nil { diff --git a/pkg/minikube/command/kic_runner_test.go b/pkg/minikube/command/kic_runner_test.go new file mode 100644 index 0000000000..63fc63a5b8 --- /dev/null +++ b/pkg/minikube/command/kic_runner_test.go @@ -0,0 +1,54 @@ +/* +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 command + +import ( + "os" + "testing" +) + +func TestKICRunner(t *testing.T) { + t.Parallel() + + t.Run("TestTempDirectory", func(t *testing.T) { + t.Parallel() + + home, err := os.UserHomeDir() + if err != nil { + t.Fatalf("failed to get user home directory: %v", err) + } + + tests := []struct { + in bool + want string + }{ + {false, ""}, + {true, home}, + } + + for _, tt := range tests { + got, err := tempDirectory(tt.in) + if err != nil { + t.Fatalf("failed to get temp directory: %v", err) + } + + if got != tt.want { + t.Errorf("tempDirectory(%t) = %s; want %s", tt.in, got, tt.want) + } + } + }) +} diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index 6d990f921e..c3800991fe 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -84,7 +84,10 @@ const ( TestDiskUsedEnv = "MINIKUBE_TEST_STORAGE_CAPACITY" // scheduled stop constants - ScheduledStopEnvFile = "/var/lib/minikube/scheduled-stop/environment" + + // ScheduledStopEnvFile is the environment file for scheduled-stop + ScheduledStopEnvFile = "/var/lib/minikube/scheduled-stop/environment" + // ScheduledStopSystemdService is the service file for scheduled-stop ScheduledStopSystemdService = "minikube-scheduled-stop" // MinikubeExistingPrefix is used to save the original environment when executing docker-env diff --git a/pkg/minikube/kubeconfig/extension.go b/pkg/minikube/kubeconfig/extension.go index c1a1321bf7..aff7cb25a8 100644 --- a/pkg/minikube/kubeconfig/extension.go +++ b/pkg/minikube/kubeconfig/extension.go @@ -25,6 +25,8 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // implementing the runtime.Object internally so we can write extensions to kubeconfig + +// Extension represents information to identify clusters and contexts type Extension struct { runtime.TypeMeta `json:",inline"` Version string `json:"version"` diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index 3b5f2d379e..1288e7117b 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -158,7 +158,7 @@ func needsTransfer(imgClient *client.Client, imgName string, cr cruntime.Manager } // CacheAndLoadImages caches and loads images to all profiles -func CacheAndLoadImages(images []string) error { +func CacheAndLoadImages(images []string, profiles []*config.Profile) error { if len(images) == 0 { return nil } @@ -173,10 +173,6 @@ func CacheAndLoadImages(images []string) error { return errors.Wrap(err, "api") } defer api.Close() - profiles, _, err := config.ListProfiles() // need to load image to all profiles - if err != nil { - return errors.Wrap(err, "list profiles") - } succeeded := []string{} failed := []string{} diff --git a/pkg/minikube/machine/ssh.go b/pkg/minikube/machine/ssh.go index 8f7cc84f86..f6b0534015 100644 --- a/pkg/minikube/machine/ssh.go +++ b/pkg/minikube/machine/ssh.go @@ -68,6 +68,7 @@ func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node, return client.Shell(args...) } +// GetSSHHostAddrPort returns the host address and port for ssh func GetSSHHostAddrPort(api libmachine.API, cc config.ClusterConfig, n config.Node) (string, int, error) { host, err := getHost(api, cc, n) if err != nil { diff --git a/pkg/minikube/node/cache.go b/pkg/minikube/node/cache.go index e775ed3ca1..0abcb26aa0 100644 --- a/pkg/minikube/node/cache.go +++ b/pkg/minikube/node/cache.go @@ -210,7 +210,7 @@ func saveImagesToTarFromConfig() error { // CacheAndLoadImagesInConfig loads the images currently in the config file // called by 'start' and 'cache reload' commands. -func CacheAndLoadImagesInConfig() error { +func CacheAndLoadImagesInConfig(profiles []*config.Profile) error { images, err := imagesInConfigFile() if err != nil { return errors.Wrap(err, "images") @@ -218,7 +218,7 @@ func CacheAndLoadImagesInConfig() error { if len(images) == 0 { return nil } - return machine.CacheAndLoadImages(images) + return machine.CacheAndLoadImages(images, profiles) } func imagesInConfigFile() ([]string, error) { diff --git a/pkg/minikube/node/start.go b/pkg/minikube/node/start.go index 2a077442bc..42f9395e69 100644 --- a/pkg/minikube/node/start.go +++ b/pkg/minikube/node/start.go @@ -145,10 +145,14 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) { wg.Add(1) go func() { - if err := CacheAndLoadImagesInConfig(); err != nil { + defer wg.Done() + profile, err := config.LoadProfile(starter.Cfg.Name) + if err != nil { + out.FailureT("Unable to load profile: {{.error}}", out.V{"error": err}) + } + if err := CacheAndLoadImagesInConfig([]*config.Profile{profile}); err != nil { out.FailureT("Unable to push cached images: {{.error}}", out.V{"error": err}) } - wg.Done() }() // enable addons, both old and new! diff --git a/pkg/minikube/reason/reason.go b/pkg/minikube/reason/reason.go index bb033bd405..fddcaea914 100644 --- a/pkg/minikube/reason/reason.go +++ b/pkg/minikube/reason/reason.go @@ -240,6 +240,7 @@ var ( GuestCert = Kind{ID: "GUEST_CERT", ExitCode: ExGuestError} GuestCpConfig = Kind{ID: "GUEST_CP_CONFIG", ExitCode: ExGuestConfig} GuestDeletion = Kind{ID: "GUEST_DELETION", ExitCode: ExGuestError} + GuestImageLoad = Kind{ID: "GUEST_IMAGE_LOAD", ExitCode: ExGuestError} GuestLoadHost = Kind{ID: "GUEST_LOAD_HOST", ExitCode: ExGuestError} GuestMount = Kind{ID: "GUEST_MOUNT", ExitCode: ExGuestError} GuestMountConflict = Kind{ID: "GUEST_MOUNT_CONFLICT", ExitCode: ExGuestConflict} diff --git a/pkg/minikube/sshutil/sshutil.go b/pkg/minikube/sshutil/sshutil.go index 94164f1046..bd1a7d2aad 100644 --- a/pkg/minikube/sshutil/sshutil.go +++ b/pkg/minikube/sshutil/sshutil.go @@ -93,6 +93,7 @@ func newSSHHost(d drivers.Driver) (*sshHost, error) { }, nil } +// KnownHost checks if this host is in the knownHosts file func KnownHost(host string, knownHosts string) bool { fd, err := os.Open(knownHosts) if err != nil { diff --git a/pkg/minikube/style/style.go b/pkg/minikube/style/style.go index 3adc368609..f7883fca96 100644 --- a/pkg/minikube/style/style.go +++ b/pkg/minikube/style/style.go @@ -45,6 +45,7 @@ type Options struct { Spinner bool } +// SpinnerCharacter is which of the spinner.CharSets to use const SpinnerCharacter = 9 // Config is a map of style name to style struct diff --git a/pkg/provision/buildroot.go b/pkg/provision/buildroot.go index 61f652c780..c085c857d4 100644 --- a/pkg/provision/buildroot.go +++ b/pkg/provision/buildroot.go @@ -76,12 +76,12 @@ Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network.target minikube-automount.service docker.socket Requires= minikube-automount.service docker.socket +StartLimitBurst=3 +StartLimitIntervalSec=60 [Service] Type=notify Restart=on-failure -StartLimitBurst=3 -StartLimitIntervalSec=60 ` if noPivot { klog.Warning("Using fundamentally insecure --no-pivot option") diff --git a/pkg/provision/ubuntu.go b/pkg/provision/ubuntu.go index 15d9c60019..330e3d40b9 100644 --- a/pkg/provision/ubuntu.go +++ b/pkg/provision/ubuntu.go @@ -79,12 +79,12 @@ BindsTo=containerd.service After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=docker.socket +StartLimitBurst=3 +StartLimitIntervalSec=60 [Service] Type=notify Restart=on-failure -StartLimitBurst=3 -StartLimitIntervalSec=60 ` if noPivot { klog.Warning("Using fundamentally insecure --no-pivot option") diff --git a/site/content/en/docs/commands/cache.md b/site/content/en/docs/commands/cache.md index 6f7eff26a9..39065402f7 100644 --- a/site/content/en/docs/commands/cache.md +++ b/site/content/en/docs/commands/cache.md @@ -47,6 +47,12 @@ Add an image to local cache. minikube cache add [flags] ``` +### Options + +``` + -- Add image to cache for all running minikube clusters +``` + ### Options inherited from parent commands ``` diff --git a/site/content/en/docs/commands/image.md b/site/content/en/docs/commands/image.md new file mode 100644 index 0000000000..e98ceb45eb --- /dev/null +++ b/site/content/en/docs/commands/image.md @@ -0,0 +1,106 @@ +--- +title: "image" +description: > + Load a local image into minikube +--- + + +## minikube image + +Load a local image into minikube + +### Synopsis + +Load a local image into minikube + +### Options inherited from parent commands + +``` + --add_dir_header If true, adds the file directory to the header of the log messages + --alsologtostderr log to standard error as well as files + -b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm") + -h, --help + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --log_file string If non-empty, use this log file + --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + --logtostderr log to standard error instead of files + --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level + -p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube") + --skip_headers If true, avoid header prefixes in the log messages + --skip_log_headers If true, avoid headers when opening log files + --stderrthreshold severity logs at or above this threshold go to stderr (default 2) + --user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username. + -v, --v Level number for the log level verbosity + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + +## minikube image help + +Help about any command + +### Synopsis + +Help provides help for any command in the application. +Simply type image help [path to command] for full details. + +```shell +minikube image help [command] [flags] +``` + +### Options inherited from parent commands + +``` + --add_dir_header If true, adds the file directory to the header of the log messages + --alsologtostderr log to standard error as well as files + -b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm") + -h, --help + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --log_file string If non-empty, use this log file + --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + --logtostderr log to standard error instead of files + --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level + -p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube") + --skip_headers If true, avoid header prefixes in the log messages + --skip_log_headers If true, avoid headers when opening log files + --stderrthreshold severity logs at or above this threshold go to stderr (default 2) + --user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username. + -v, --v Level number for the log level verbosity + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + +## minikube image load + +Load a local image into minikube + +### Synopsis + +Load a local image into minikube + +```shell +minikube image load [flags] +``` + +### Options inherited from parent commands + +``` + --add_dir_header If true, adds the file directory to the header of the log messages + --alsologtostderr log to standard error as well as files + -b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm") + -h, --help + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory + --log_file string If non-empty, use this log file + --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + --logtostderr log to standard error instead of files + --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level + -p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube") + --skip_headers If true, avoid header prefixes in the log messages + --skip_log_headers If true, avoid headers when opening log files + --stderrthreshold severity logs at or above this threshold go to stderr (default 2) + --user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username. + -v, --v Level number for the log level verbosity + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging +``` + diff --git a/test/integration/functional_test.go b/test/integration/functional_test.go index d52ae2f864..aca25d0721 100644 --- a/test/integration/functional_test.go +++ b/test/integration/functional_test.go @@ -127,6 +127,7 @@ func TestFunctional(t *testing.T) { {"UpdateContextCmd", validateUpdateContextCmd}, {"DockerEnv", validateDockerEnv}, {"NodeLabels", validateNodeLabels}, + {"LoadImage", validateLoadImage}, } for _, tc := range tests { tc := tc @@ -158,6 +159,48 @@ func validateNodeLabels(ctx context.Context, t *testing.T, profile string) { } } +// validateLoadImage makes sure that `minikube load image` works as expected +func validateLoadImage(ctx context.Context, t *testing.T, profile string) { + if NoneDriver() { + t.Skip("load image not available on none driver") + } + defer PostMortemLogs(t, profile) + // pull busybox + busybox := "busybox:latest" + rr, err := Run(t, exec.CommandContext(ctx, "docker", "pull", busybox)) + if err != nil { + t.Fatalf("starting minikube: %v\n%s", err, rr.Output()) + } + + // tag busybox + newImage := fmt.Sprintf("busybox:%s", profile) + rr, err = Run(t, exec.CommandContext(ctx, "docker", "tag", busybox, newImage)) + if err != nil { + t.Fatalf("starting minikube: %v\n%s", err, rr.Output()) + } + + // try to load the new image into minikube + rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "image", "load", newImage)) + if err != nil { + t.Fatalf("loading image into minikube: %v\n%s", err, rr.Output()) + } + + // make sure the image was correctly loaded + var cmd *exec.Cmd + if ContainerRuntime() == "docker" { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images", "--format", "{{.Repository}}:{{.Tag}}") + } else { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "sudo", "ctr", "-n=k8s.io", "image", "ls") + } + rr, err = Run(t, cmd) + if err != nil { + t.Fatalf("listing images: %v\n%s", err, rr.Output()) + } + if !strings.Contains(rr.Output(), newImage) { + t.Fatalf("expected %s to be loaded into minikube but the image is not there", newImage) + } +} + // check functionality of minikube after evaling docker-env // TODO: Add validatePodmanEnv for crio runtime: #10231 func validateDockerEnv(ctx context.Context, t *testing.T, profile string) { diff --git a/test/integration/preload_test.go b/test/integration/preload_test.go index e0c868f9a0..be4ea62501 100644 --- a/test/integration/preload_test.go +++ b/test/integration/preload_test.go @@ -49,9 +49,15 @@ func TestPreload(t *testing.T) { t.Fatalf("%s failed: %v", rr.Command(), err) } - // Now, pull the busybox image into the VMs docker daemon + // Now, pull the busybox image into minikube image := "busybox" - rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "pull", image)) + var cmd *exec.Cmd + if ContainerRuntime() == "docker" { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "pull", image) + } else { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "sudo", "crictl", "pull", image) + } + rr, err = Run(t, cmd) if err != nil { t.Fatalf("%s failed: %v", rr.Command(), err) } @@ -65,7 +71,12 @@ func TestPreload(t *testing.T) { if err != nil { t.Fatalf("%s failed: %v", rr.Command(), err) } - rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images")) + if ContainerRuntime() == "docker" { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "docker", "images") + } else { + cmd = exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "--", "sudo", "crictl", "image", "ls") + } + rr, err = Run(t, cmd) if err != nil { t.Fatalf("%s failed: %v", rr.Command(), err) }