Merge branch 'master' of github.com:kubernetes/minikube into compare
commit
48b5a1e493
65
CHANGELOG.md
65
CHANGELOG.md
|
|
@ -1,5 +1,69 @@
|
|||
# Release Notes
|
||||
|
||||
## Version 1.6.1 - 2019-12-11
|
||||
|
||||
A special bugfix release to fix a Windows regression:
|
||||
|
||||
* lock names: Remove uid suffix & hash entire path [#6059](https://github.com/kubernetes/minikube/pull/6059)
|
||||
|
||||
## Version 1.6.0 - 2019-12-10
|
||||
|
||||
* Update default k8s version to v1.17.0 [#6042](https://github.com/kubernetes/minikube/pull/6042)
|
||||
* Make Kubernetes version sticky for a cluster instead of auto-upgrading [#5798](https://github.com/kubernetes/minikube/pull/5798)
|
||||
* cache add: load images to all profiles & skip previously cached images [#5987](https://github.com/kubernetes/minikube/pull/5987)
|
||||
* Update dashboard to 2.0.0b8 and pre-cache it again [#6039](https://github.com/kubernetes/minikube/pull/6039)
|
||||
* Pre-cache the latest kube-addon-manager [#5935](https://github.com/kubernetes/minikube/pull/5935)
|
||||
* Add sch_netem kernel module for network emulation [#6038](https://github.com/kubernetes/minikube/pull/6038)
|
||||
* Don't use bash as the entrypoint for docker [#5818](https://github.com/kubernetes/minikube/pull/5818)
|
||||
* Make lock names uid and path specific to avoid conflicts [#5912](https://github.com/kubernetes/minikube/pull/5912)
|
||||
* Remove deprecated annotation storageclass.beta.kubernetes.io [#5954](https://github.com/kubernetes/minikube/pull/5954)
|
||||
* show status in profile list [#5988](https://github.com/kubernetes/minikube/pull/5988)
|
||||
* Use newer gvisor version [#6000](https://github.com/kubernetes/minikube/pull/6000)
|
||||
* Adds dm-crypt support [#5739](https://github.com/kubernetes/minikube/pull/5739)
|
||||
* Add performance analysis packages to minikube ISO [#5942](https://github.com/kubernetes/minikube/pull/5942)
|
||||
|
||||
Thanks goes out to the merry band of Kubernetes contributors that made this release possible:
|
||||
|
||||
- Anders F Björklund
|
||||
- Anukul Sangwan
|
||||
- Guilherme Pellizzetti
|
||||
- Jan Ahrens
|
||||
- Karuppiah Natarajan
|
||||
- Laura-Marie Henning
|
||||
- Medya Ghazizadeh
|
||||
- Nanik T
|
||||
- Olivier Lemasle
|
||||
- Priya Wadhwa
|
||||
- Sharif Elgamal
|
||||
- Thomas Strömberg
|
||||
- Vasyl Purchel
|
||||
- Wietse Muizelaar
|
||||
|
||||
## Version 1.6.0-beta.1 - 2019-11-26
|
||||
|
||||
* cri-o v1.16.0 [#5970](https://github.com/kubernetes/minikube/pull/5970)
|
||||
* Update default k8s version to 1.17.0-rc.1 [#5973](https://github.com/kubernetes/minikube/pull/5973)
|
||||
* Update crictl to v1.16.1 [#5972](https://github.com/kubernetes/minikube/pull/5972)
|
||||
* Update docker to v19.03.5 [#5914](https://github.com/kubernetes/minikube/pull/5914)
|
||||
* Fix profile list for non existenting folder [#5955](https://github.com/kubernetes/minikube/pull/5955)
|
||||
* Upgrade podman to 1.6.3 [#5971](https://github.com/kubernetes/minikube/pull/5971)
|
||||
* Fix validation of container-runtime config [#5964](https://github.com/kubernetes/minikube/pull/5964)
|
||||
* Add option for virtualbox users to set nat-nic-type [#5960](https://github.com/kubernetes/minikube/pull/5960)
|
||||
* Upgrade buildroot minor version to 2019.02.7 [#5967](https://github.com/kubernetes/minikube/pull/5967)
|
||||
* dashboard: Update to latest images (2.0.0-beta6) [#5934](https://github.com/kubernetes/minikube/pull/5934)
|
||||
|
||||
Huge thank you for this release towards our contributors:
|
||||
- Adam Crowder
|
||||
- Anders F Björklund
|
||||
- David Newman
|
||||
- Harsimran Singh Maan
|
||||
- Kenta Iso
|
||||
- Medya Ghazizadeh
|
||||
- Reuven Harrison
|
||||
- Sharif Elgamal
|
||||
- Thomas Stromberg
|
||||
- yuxiaobo
|
||||
|
||||
## Version 1.6.0-beta.0 - 2019-11-15
|
||||
|
||||
* Update DefaultKubernetesVersion to v1.17.0-beta.1 to prepare for betas [#5925](https://github.com/kubernetes/minikube/pull/5925)
|
||||
|
|
@ -30,7 +94,6 @@ Huge thank you for this release towards our contributors:
|
|||
- Steffen Gransow
|
||||
- Thomas Strömberg
|
||||
|
||||
|
||||
## Version 1.5.2 - 2019-10-31 (Happy Halloween!)
|
||||
|
||||
* service: fix --url mode [#5790](https://github.com/kubernetes/minikube/pull/5790)
|
||||
|
|
|
|||
22
Makefile
22
Makefile
|
|
@ -15,12 +15,12 @@
|
|||
# Bump these on release - and please check ISO_VERSION for correctness.
|
||||
VERSION_MAJOR ?= 1
|
||||
VERSION_MINOR ?= 6
|
||||
VERSION_BUILD ?= 0-beta.0
|
||||
VERSION_BUILD ?= 1
|
||||
RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).${VERSION_BUILD}
|
||||
VERSION ?= v$(RAW_VERSION)
|
||||
|
||||
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
|
||||
ISO_VERSION ?= v1.5.1
|
||||
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).0
|
||||
# Dashes are valid in semver, but not Linux packaging. Use ~ to delimit alpha/beta
|
||||
DEB_VERSION ?= $(subst -,~,$(RAW_VERSION))
|
||||
RPM_VERSION ?= $(DEB_VERSION)
|
||||
|
|
@ -60,7 +60,8 @@ GOLINT_GOGC ?= 100
|
|||
GOLINT_OPTIONS = --timeout 4m \
|
||||
--build-tags "${MINIKUBE_INTEGRATION_BUILD_TAGS}" \
|
||||
--enable goimports,gocritic,golint,gocyclo,misspell,nakedret,stylecheck,unconvert,unparam,dogsled \
|
||||
--exclude 'variable on range scope.*in function literal|ifElseChain'
|
||||
--exclude 'variable on range scope.*in function literal|ifElseChain' \
|
||||
--skip-files "pkg/minikube/translate/translations.go|pkg/minikube/assets/assets.go"
|
||||
|
||||
# Major version of gvisor image. Increment when there are breaking changes.
|
||||
GVISOR_IMAGE_VERSION ?= 2
|
||||
|
|
@ -118,7 +119,7 @@ HYPERKIT_LDFLAGS := -X k8s.io/minikube/pkg/drivers/hyperkit.version=$(VERSION) -
|
|||
|
||||
# $(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 --entrypoint /bin/bash $(1) -c '$(2)'
|
||||
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)'
|
||||
endef
|
||||
|
||||
ifeq ($(BUILD_IN_DOCKER),y)
|
||||
|
|
@ -436,7 +437,10 @@ out/minikube-installer.exe: out/minikube-windows-amd64.exe
|
|||
|
||||
out/docker-machine-driver-hyperkit:
|
||||
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(HYPERKIT_BUILD_IMAGE),CC=o64-clang CXX=o64-clang++ /usr/bin/make $@)
|
||||
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 --entrypoint "" \
|
||||
$(HYPERKIT_BUILD_IMAGE) /bin/bash -c 'CC=o64-clang CXX=o64-clang++ /usr/bin/make $@'
|
||||
else
|
||||
GOOS=darwin CGO_ENABLED=1 go build \
|
||||
-ldflags="$(HYPERKIT_LDFLAGS)" \
|
||||
|
|
@ -445,7 +449,7 @@ endif
|
|||
|
||||
hyperkit_in_docker:
|
||||
rm -f out/docker-machine-driver-hyperkit
|
||||
$(call DOCKER,$(HYPERKIT_BUILD_IMAGE),CC=o64-clang CXX=o64-clang++ /usr/bin/make out/docker-machine-driver-hyperkit)
|
||||
$(MAKE) MINIKUBE_BUILD_IN_DOCKER=y out/docker-machine-driver-hyperkit
|
||||
|
||||
.PHONY: install-hyperkit-driver
|
||||
install-hyperkit-driver: out/docker-machine-driver-hyperkit ## Install hyperkit to local machine
|
||||
|
|
@ -582,7 +586,11 @@ site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo ## Serv
|
|||
|
||||
.PHONY: out/mkcmp
|
||||
out/mkcmp:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/main.go
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/mkcmp/main.go
|
||||
|
||||
.PHONY: out/performance-monitor
|
||||
out/performance-monitor:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/monitor/monitor.go
|
||||
|
||||
.PHONY: compare
|
||||
compare: out/mkcmp out/minikube
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ var ProfileCmd = &cobra.Command{
|
|||
if err != nil {
|
||||
exit.WithError("Setting profile failed", err)
|
||||
}
|
||||
cc, err := pkgConfig.Load()
|
||||
cc, err := pkgConfig.Load(profile)
|
||||
// might err when loading older version of cfg file that doesn't have KeepContext field
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
out.ErrT(out.Sad, `Error loading profile config: {{.error}}`, out.V{"error": err})
|
||||
|
|
|
|||
|
|
@ -23,10 +23,13 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -58,7 +61,7 @@ var printProfilesTable = func() {
|
|||
var validData [][]string
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version"})
|
||||
table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version", "Status"})
|
||||
table.SetAutoFormatHeaders(false)
|
||||
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
|
||||
table.SetCenterSeparator("|")
|
||||
|
|
@ -67,8 +70,18 @@ var printProfilesTable = func() {
|
|||
if len(validProfiles) == 0 || err != nil {
|
||||
exit.UsageT("No minikube profile was found. You can create one using `minikube start`.")
|
||||
}
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
glog.Infof("failed to get machine api client %v", err)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
for _, p := range validProfiles {
|
||||
validData = append(validData, []string{p.Name, p.Config[0].VMDriver, p.Config[0].KubernetesConfig.NodeIP, strconv.Itoa(p.Config[0].KubernetesConfig.NodePort), p.Config[0].KubernetesConfig.KubernetesVersion})
|
||||
p.Status, err = cluster.GetHostStatus(api, p.Name)
|
||||
if err != nil {
|
||||
glog.Infof("error getting host status for %v", err)
|
||||
}
|
||||
validData = append(validData, []string{p.Name, p.Config[0].VMDriver, p.Config[0].KubernetesConfig.NodeIP, strconv.Itoa(p.Config[0].KubernetesConfig.NodePort), p.Config[0].KubernetesConfig.KubernetesVersion, p.Status})
|
||||
}
|
||||
|
||||
table.AppendBulk(validData)
|
||||
|
|
@ -93,7 +106,20 @@ var printProfilesTable = func() {
|
|||
}
|
||||
|
||||
var printProfilesJSON = func() {
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
glog.Infof("failed to get machine api client %v", err)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
validProfiles, invalidProfiles, err := config.ListProfiles()
|
||||
for _, v := range validProfiles {
|
||||
status, err := cluster.GetHostStatus(api, v.Name)
|
||||
if err != nil {
|
||||
glog.Infof("error getting host status for %v", err)
|
||||
}
|
||||
v.Status = status
|
||||
}
|
||||
|
||||
var valid []*config.Profile
|
||||
var invalid []*config.Profile
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
|
|
@ -137,7 +138,7 @@ func EnableOrDisableAddon(name string, val string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
cfg, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
exit.WithCodeT(exit.Data, "Unable to load config: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,17 +122,16 @@ func TestValidateProfile(t *testing.T) {
|
|||
profileName: "82374328742_2974224498",
|
||||
},
|
||||
{
|
||||
profileName: "minikube",
|
||||
profileName: "validate_test",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
profileNam := test.profileName
|
||||
expectedMsg := fmt.Sprintf("profile %q not found", test.profileName)
|
||||
|
||||
expected := fmt.Sprintf("profile %q not found", test.profileName)
|
||||
err, ok := ValidateProfile(profileNam)
|
||||
if !ok && err.Error() != expectedMsg {
|
||||
t.Errorf("Didnt receive expected message")
|
||||
if !ok && err.Error() != expected {
|
||||
t.Errorf("got error %q, expected %q", err, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
|
|
@ -158,7 +159,7 @@ func IsValidRuntime(name string, runtime string) error {
|
|||
|
||||
// IsContainerdRuntime is a validator which returns an error if the current runtime is not containerd
|
||||
func IsContainerdRuntime(_, _ string) error {
|
||||
config, err := config.Load()
|
||||
config, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
return fmt.Errorf("config.Load: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,11 @@ import (
|
|||
"github.com/pkg/browser"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
configcmd "k8s.io/minikube/cmd/minikube/cmd/config"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
pkg_config "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
|
|
@ -57,7 +59,7 @@ var dashboardCmd = &cobra.Command{
|
|||
Short: "Access the kubernetes dashboard running within the minikube cluster",
|
||||
Long: `Access the kubernetes dashboard running within the minikube cluster`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cc, err := pkg_config.Load()
|
||||
cc, err := pkg_config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
exit.WithError("Error loading profile config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ func DeleteProfiles(profiles []*pkg_config.Profile) []error {
|
|||
err := deleteProfile(profile)
|
||||
|
||||
if err != nil {
|
||||
mm, loadErr := cluster.LoadMachine(profile.Name)
|
||||
mm, loadErr := machine.Load(profile.Name)
|
||||
|
||||
if !profile.IsValid() || (loadErr != nil || !mm.IsValid()) {
|
||||
invalidProfileDeletionErrs := deleteInvalidProfile(profile)
|
||||
|
|
@ -187,8 +187,7 @@ func deleteProfile(profile *pkg_config.Profile) error {
|
|||
return DeletionError{Err: delErr, Errtype: Fatal}
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
cc, err := pkg_config.Load()
|
||||
cc, err := pkg_config.Load(profile.Name)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
delErr := profileDeletionErr(profile.Name, fmt.Sprintf("error loading profile config: %v", err))
|
||||
return DeletionError{Err: delErr, Errtype: MissingProfile}
|
||||
|
|
@ -263,7 +262,7 @@ func deleteInvalidProfile(profile *pkg_config.Profile) []error {
|
|||
}
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
pathToMachine := localpath.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
err := os.RemoveAll(pathToMachine)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/otiai10/copy"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
)
|
||||
|
|
@ -117,7 +116,7 @@ func TestDeleteProfile(t *testing.T) {
|
|||
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
pathToMachine := localpath.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ var dockerEnvCmd = &cobra.Command{
|
|||
exit.WithError("Error getting client", err)
|
||||
}
|
||||
defer api.Close()
|
||||
cc, err := config.Load()
|
||||
cc, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/mcnerror"
|
||||
"github.com/pkg/errors"
|
||||
"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"
|
||||
|
|
@ -38,7 +39,7 @@ var ipCmd = &cobra.Command{
|
|||
}
|
||||
defer api.Close()
|
||||
|
||||
cc, err := config.Load()
|
||||
cc, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
pkg_config "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
|
|
@ -48,7 +50,7 @@ kubectl get pods --namespace kube-system`,
|
|||
}
|
||||
defer api.Close()
|
||||
|
||||
cc, err := pkg_config.Load()
|
||||
cc, err := pkg_config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
out.ErrLn("Error loading profile config: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ var logsCmd = &cobra.Command{
|
|||
Short: "Gets the logs of the running instance, used for debugging minikube, not user code.",
|
||||
Long: `Gets the logs of the running instance, used for debugging minikube, not user code.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cfg, err := config.Load()
|
||||
cfg, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
|
|
@ -102,7 +103,7 @@ var mountCmd = &cobra.Command{
|
|||
exit.WithError("Error getting client", err)
|
||||
}
|
||||
defer api.Close()
|
||||
cc, err := config.Load()
|
||||
cc, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"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/localpath"
|
||||
|
|
@ -32,7 +33,7 @@ var sshKeyCmd = &cobra.Command{
|
|||
Short: "Retrieve the ssh identity key path of the specified cluster",
|
||||
Long: "Retrieve the ssh identity key path of the specified cluster.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cc, err := config.Load()
|
||||
cc, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Getting machine config failed", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ var sshCmd = &cobra.Command{
|
|||
exit.WithError("Error getting client", err)
|
||||
}
|
||||
defer api.Close()
|
||||
cc, err := config.Load()
|
||||
cc, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
cfg "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
|
|
@ -180,7 +181,7 @@ func initMinikubeFlags() {
|
|||
|
||||
// initKubernetesFlags inits the commandline flags for kubernetes related options
|
||||
func initKubernetesFlags() {
|
||||
startCmd.Flags().String(kubernetesVersion, constants.DefaultKubernetesVersion, "The kubernetes version that the minikube VM will use (ex: v1.2.3)")
|
||||
startCmd.Flags().String(kubernetesVersion, "", "The kubernetes version that the minikube VM will use (ex: v1.2.3)")
|
||||
startCmd.Flags().Var(&extraOptions, "extra-config",
|
||||
`A set of key=value pairs that describe configuration that may be passed to different components.
|
||||
The key should be '.' separated, and the first part before the dot is the component to apply the configuration to.
|
||||
|
|
@ -287,7 +288,7 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
registryMirror = viper.GetStringSlice("registry_mirror")
|
||||
}
|
||||
|
||||
existing, err := cfg.Load()
|
||||
existing, err := cfg.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
exit.WithCodeT(exit.Data, "Unable to load config: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
|
@ -352,7 +353,7 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// setup kubeadm (must come after setupKubeconfig)
|
||||
bs := setupKubeAdm(machineAPI, config.KubernetesConfig)
|
||||
bs := setupKubeAdm(machineAPI, config)
|
||||
|
||||
// pull images or restart cluster
|
||||
bootstrapCluster(bs, cr, mRunner, config.KubernetesConfig, preExists, isUpgrade)
|
||||
|
|
@ -645,7 +646,7 @@ func validateDriver(name string, existing *cfg.MachineConfig) {
|
|||
exit.WithCodeT(exit.Config, "Exiting.")
|
||||
}
|
||||
|
||||
func selectImageRepository(mirrorCountry string, k8sVersion string) (bool, string, error) {
|
||||
func selectImageRepository(mirrorCountry string) (bool, string, error) {
|
||||
var tryCountries []string
|
||||
var fallback string
|
||||
glog.Infof("selecting image repository for country %s ...", mirrorCountry)
|
||||
|
|
@ -673,7 +674,7 @@ func selectImageRepository(mirrorCountry string, k8sVersion string) (bool, strin
|
|||
}
|
||||
|
||||
checkRepository := func(repo string) error {
|
||||
pauseImage := images.PauseImage(repo, k8sVersion)
|
||||
pauseImage := images.Pause(repo)
|
||||
ref, err := name.ParseReference(pauseImage, name.WeakValidation)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -729,7 +730,7 @@ func validateUser(drvName string) {
|
|||
if !useForce {
|
||||
os.Exit(exit.Permissions)
|
||||
}
|
||||
_, err = cfg.Load()
|
||||
_, err = cfg.Load(viper.GetString(config.MachineProfile))
|
||||
if err == nil || !os.IsNotExist(err) {
|
||||
out.T(out.Tip, "Tip: To remove this root owned cluster, run: sudo {{.cmd}} delete", out.V{"cmd": minikubeCmd()})
|
||||
}
|
||||
|
|
@ -866,7 +867,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, drvName string)
|
|||
repository := viper.GetString(imageRepository)
|
||||
mirrorCountry := strings.ToLower(viper.GetString(imageMirrorCountry))
|
||||
if strings.ToLower(repository) == "auto" || mirrorCountry != "" {
|
||||
found, autoSelectedRepository, err := selectImageRepository(mirrorCountry, k8sVersion)
|
||||
found, autoSelectedRepository, err := selectImageRepository(mirrorCountry)
|
||||
if err != nil {
|
||||
exit.WithError("Failed to check main repository and mirrors for images for images", err)
|
||||
}
|
||||
|
|
@ -1108,7 +1109,7 @@ func tryRegistry(r command.Runner) {
|
|||
|
||||
repo := viper.GetString(imageRepository)
|
||||
if repo == "" {
|
||||
repo = images.DefaultImageRepo
|
||||
repo = images.DefaultKubernetesRepo
|
||||
}
|
||||
|
||||
opts = append(opts, fmt.Sprintf("https://%s/", repo))
|
||||
|
|
@ -1120,15 +1121,20 @@ func tryRegistry(r command.Runner) {
|
|||
|
||||
// getKubernetesVersion ensures that the requested version is reasonable
|
||||
func getKubernetesVersion(old *cfg.MachineConfig) (string, bool) {
|
||||
rawVersion := viper.GetString(kubernetesVersion)
|
||||
paramVersion := viper.GetString(kubernetesVersion)
|
||||
isUpgrade := false
|
||||
if rawVersion == "" {
|
||||
rawVersion = constants.DefaultKubernetesVersion
|
||||
|
||||
if paramVersion == "" { // if the user did not specify any version then ...
|
||||
if old != nil { // .. use the old version from config
|
||||
paramVersion = old.KubernetesConfig.KubernetesVersion
|
||||
} else { // .. otherwise use the default version
|
||||
paramVersion = constants.DefaultKubernetesVersion
|
||||
}
|
||||
}
|
||||
|
||||
nvs, err := semver.Make(strings.TrimPrefix(rawVersion, version.VersionPrefix))
|
||||
nvs, err := semver.Make(strings.TrimPrefix(paramVersion, version.VersionPrefix))
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Data, `Unable to parse "{{.kubernetes_version}}": {{.error}}`, out.V{"kubernetes_version": rawVersion, "error": err})
|
||||
exit.WithCodeT(exit.Data, `Unable to parse "{{.kubernetes_version}}": {{.error}}`, out.V{"kubernetes_version": paramVersion, "error": err})
|
||||
}
|
||||
nv := version.VersionPrefix + nvs.String()
|
||||
|
||||
|
|
@ -1140,6 +1146,10 @@ func getKubernetesVersion(old *cfg.MachineConfig) (string, bool) {
|
|||
if err != nil {
|
||||
exit.WithCodeT(exit.Data, "Unable to parse oldest Kubernetes version from constants: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
defaultVersion, err := semver.Make(strings.TrimPrefix(constants.DefaultKubernetesVersion, version.VersionPrefix))
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Data, "Unable to parse default Kubernetes version from constants: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
||||
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})
|
||||
|
|
@ -1168,15 +1178,18 @@ func getKubernetesVersion(old *cfg.MachineConfig) (string, bool) {
|
|||
* Reuse the existing cluster with Kubernetes v{{.old}} or newer: Run "minikube start {{.profile}} --kubernetes-version={{.old}}"`, out.V{"new": nvs, "old": ovs, "profile": profileArg})
|
||||
|
||||
}
|
||||
if defaultVersion.GT(nvs) {
|
||||
out.T(out.ThumbsUp, "Kubernetes {{.new}} is now available. If you would like to upgrade, specify: --kubernetes-version={{.new}}", out.V{"new": defaultVersion})
|
||||
}
|
||||
|
||||
if nvs.GT(ovs) {
|
||||
out.T(out.ThumbsUp, "Upgrading from Kubernetes {{.old}} to {{.new}}", out.V{"old": ovs, "new": nvs})
|
||||
isUpgrade = true
|
||||
}
|
||||
return nv, isUpgrade
|
||||
}
|
||||
|
||||
// setupKubeAdm adds any requested files into the VM before Kubernetes is started
|
||||
func setupKubeAdm(mAPI libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Bootstrapper {
|
||||
func setupKubeAdm(mAPI libmachine.API, config cfg.MachineConfig) bootstrapper.Bootstrapper {
|
||||
bs, err := getClusterBootstrapper(mAPI, viper.GetString(cmdcfg.Bootstrapper))
|
||||
if err != nil {
|
||||
exit.WithError("Failed to get bootstrapper", err)
|
||||
|
|
@ -1185,10 +1198,10 @@ func setupKubeAdm(mAPI libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Boo
|
|||
out.T(out.Option, "{{.extra_option_component_name}}.{{.key}}={{.value}}", out.V{"extra_option_component_name": eo.Component, "key": eo.Key, "value": eo.Value})
|
||||
}
|
||||
// Loads cached images, generates config files, download binaries
|
||||
if err := bs.UpdateCluster(kc); err != nil {
|
||||
if err := bs.UpdateCluster(config); err != nil {
|
||||
exit.WithError("Failed to update cluster", err)
|
||||
}
|
||||
if err := bs.SetupCerts(kc); err != nil {
|
||||
if err := bs.SetupCerts(config.KubernetesConfig); err != nil {
|
||||
exit.WithError("Failed to setup certs", err)
|
||||
}
|
||||
return bs
|
||||
|
|
|
|||
|
|
@ -22,9 +22,64 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
cfg "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
func TestGetKuberneterVersion(t *testing.T) {
|
||||
var tests = []struct {
|
||||
description string
|
||||
expectedVersion string
|
||||
paramVersion string
|
||||
upgrade bool
|
||||
cfg *cfg.MachineConfig
|
||||
}{
|
||||
{
|
||||
description: "kubernetes-version not given, no config",
|
||||
expectedVersion: constants.DefaultKubernetesVersion,
|
||||
paramVersion: "",
|
||||
upgrade: false,
|
||||
},
|
||||
{
|
||||
description: "kubernetes-version not given, config available",
|
||||
expectedVersion: "v1.15.0",
|
||||
paramVersion: "",
|
||||
upgrade: false,
|
||||
cfg: &cfg.MachineConfig{KubernetesConfig: cfg.KubernetesConfig{KubernetesVersion: "v1.15.0"}},
|
||||
},
|
||||
{
|
||||
description: "kubernetes-version given, no config",
|
||||
expectedVersion: "v1.15.0",
|
||||
paramVersion: "v1.15.0",
|
||||
upgrade: false,
|
||||
},
|
||||
{
|
||||
description: "kubernetes-version given, config available",
|
||||
expectedVersion: "v1.16.0",
|
||||
paramVersion: "v1.16.0",
|
||||
upgrade: true,
|
||||
cfg: &cfg.MachineConfig{KubernetesConfig: cfg.KubernetesConfig{KubernetesVersion: "v1.15.0"}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
viper.SetDefault(kubernetesVersion, test.paramVersion)
|
||||
version, upgrade := getKubernetesVersion(test.cfg)
|
||||
|
||||
// check whether we are getting the expected version
|
||||
if version != test.expectedVersion {
|
||||
t.Fatalf("test failed because the expected version %s is not returned", test.expectedVersion)
|
||||
}
|
||||
|
||||
// check whether the upgrade flag is correct
|
||||
if test.upgrade != upgrade {
|
||||
t.Fatalf("test failed expected upgrade is %t", test.upgrade)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateCfgFromFlagsHTTPProxyHandling(t *testing.T) {
|
||||
viper.SetDefault(memory, defaultMemorySize)
|
||||
viper.SetDefault(humanReadableDiskSize, defaultDiskSize)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"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"
|
||||
|
|
@ -76,11 +77,11 @@ var tunnelCmd = &cobra.Command{
|
|||
cancel()
|
||||
}()
|
||||
|
||||
cc, err := config.Load()
|
||||
cfg, err := config.Load(viper.GetString(config.MachineProfile))
|
||||
if err != nil {
|
||||
exit.WithError("Error getting config", err)
|
||||
}
|
||||
done, err := manager.StartTunnel(ctx, cc.Name, api, config.DefaultLoader, clientset.CoreV1())
|
||||
done, err := manager.StartTunnel(ctx, cfg.Name, api, config.DefaultLoader, clientset.CoreV1())
|
||||
if err != nil {
|
||||
exit.WithError("error starting tunnel", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
|
|
@ -45,7 +47,13 @@ var updateContextCmd = &cobra.Command{
|
|||
if err != nil {
|
||||
exit.WithError("Error host driver ip status", err)
|
||||
}
|
||||
updated, err := kubeconfig.UpdateIP(ip, machineName, constants.KubeconfigPath)
|
||||
updated := false
|
||||
kubeConfigPath := os.Getenv("KUBECONFIG")
|
||||
if kubeConfigPath == "" {
|
||||
updated, err = kubeconfig.UpdateIP(ip, machineName, constants.KubeconfigPath)
|
||||
} else {
|
||||
updated, err = kubeconfig.UpdateIP(ip, machineName, kubeConfigPath)
|
||||
}
|
||||
if err != nil {
|
||||
exit.WithError("update config", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
package main
|
||||
|
||||
import "k8s.io/minikube/cmd/performance/cmd"
|
||||
import "k8s.io/minikube/cmd/performance/mkcmp/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for {
|
||||
if err := analyzePerformance(context.Background()); err != nil {
|
||||
log.Printf("error executing performance analysis: %v", err)
|
||||
}
|
||||
time.Sleep(10 * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
// analyzePerformance is responsible for:
|
||||
// 1. collecting PRs to run performance analysis on
|
||||
// 2. running mkcmp against those PRs
|
||||
// 3. commenting results on those PRs
|
||||
func analyzePerformance(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -89,7 +89,8 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: kubernetes-dashboard
|
||||
image: kubernetesui/dashboard:v2.0.0-beta6
|
||||
# WARNING: This must match pkg/minikube/bootstrapper/images/images.go
|
||||
image: kubernetesui/dashboard:v2.0.0-beta8
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
protocol: TCP
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ TODO
|
|||
|
||||
### Add the test ingress
|
||||
```bash
|
||||
kubectl apply -f https://github.com/kubernetes/minikube/blob/master/deploy/addons/ingress-dns/example/example.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/minikube/master/deploy/addons/ingress-dns/example/example.yaml
|
||||
```
|
||||
Note: Minimum Kubernetes version for example ingress is 1.14.7
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ metadata:
|
|||
kubernetes.io/minikube-addons: storage-provisioner-gluster
|
||||
addonmanager.kubernetes.io/mode: EnsureExists
|
||||
annotations:
|
||||
storageclass.beta.kubernetes.io/is-default-class: "true"
|
||||
storageclass.kubernetes.io/is-default-class: "true"
|
||||
provisioner: gluster.org/glusterfile
|
||||
reclaimPolicy: Delete
|
||||
parameters:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ CONFIG_POSIX_MQUEUE=y
|
|||
CONFIG_AUDIT=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_PREEMPT_VOLUNTARY=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
|
|
@ -29,29 +30,11 @@ CONFIG_BLK_DEV_INITRD=y
|
|||
CONFIG_BPF_SYSCALL=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_OSF_PARTITION=y
|
||||
CONFIG_AMIGA_PARTITION=y
|
||||
CONFIG_MAC_PARTITION=y
|
||||
CONFIG_BSD_DISKLABEL=y
|
||||
CONFIG_MINIX_SUBPARTITION=y
|
||||
CONFIG_SOLARIS_X86_PARTITION=y
|
||||
CONFIG_UNIXWARE_DISKLABEL=y
|
||||
CONFIG_SGI_PARTITION=y
|
||||
CONFIG_SUN_PARTITION=y
|
||||
CONFIG_KARMA_PARTITION=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HYPERVISOR_GUEST=y
|
||||
CONFIG_PARAVIRT_SPINLOCKS=y
|
||||
CONFIG_KVM_DEBUG_FS=y
|
||||
CONFIG_CALGARY_IOMMU=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_PREEMPT_VOLUNTARY=y
|
||||
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
|
||||
CONFIG_MICROCODE_AMD=y
|
||||
CONFIG_X86_MSR=y
|
||||
|
|
@ -71,13 +54,34 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
|||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_X86_ACPI_CPUFREQ=y
|
||||
CONFIG_PCI_MMCONFIG=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
CONFIG_PCCARD=y
|
||||
CONFIG_YENTA=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_IA32_EMULATION=y
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_KVM=m
|
||||
CONFIG_KVM_INTEL=m
|
||||
CONFIG_KVM_AMD=m
|
||||
CONFIG_VHOST_NET=m
|
||||
CONFIG_VHOST_VSOCK=m
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_OSF_PARTITION=y
|
||||
CONFIG_AMIGA_PARTITION=y
|
||||
CONFIG_MAC_PARTITION=y
|
||||
CONFIG_BSD_DISKLABEL=y
|
||||
CONFIG_MINIX_SUBPARTITION=y
|
||||
CONFIG_SOLARIS_X86_PARTITION=y
|
||||
CONFIG_UNIXWARE_DISKLABEL=y
|
||||
CONFIG_SGI_PARTITION=y
|
||||
CONFIG_SUN_PARTITION=y
|
||||
CONFIG_KARMA_PARTITION=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
|
|
@ -226,8 +230,6 @@ CONFIG_IP_VS_SH=m
|
|||
CONFIG_IP_VS_SED=m
|
||||
CONFIG_IP_VS_NQ=m
|
||||
CONFIG_IP_VS_NFCT=y
|
||||
CONFIG_NF_CONNTRACK_IPV4=m
|
||||
CONFIG_NF_SOCKET_IPV4=m
|
||||
CONFIG_NF_LOG_ARP=m
|
||||
CONFIG_IP_NF_IPTABLES=y
|
||||
CONFIG_IP_NF_FILTER=y
|
||||
|
|
@ -238,8 +240,6 @@ CONFIG_IP_NF_TARGET_NETMAP=m
|
|||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=y
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_NF_CONNTRACK_IPV6=m
|
||||
CONFIG_NF_SOCKET_IPV6=m
|
||||
CONFIG_IP6_NF_IPTABLES=y
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
|
||||
CONFIG_IP6_NF_FILTER=y
|
||||
|
|
@ -268,14 +268,15 @@ CONFIG_BRIDGE_EBT_LOG=m
|
|||
CONFIG_BRIDGE_EBT_NFLOG=m
|
||||
CONFIG_BRIDGE=m
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_SCH_NETEM=y
|
||||
CONFIG_NET_SCH_INGRESS=m
|
||||
CONFIG_NET_CLS_U32=m
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_NET_CLS_BPF=m
|
||||
CONFIG_NET_EMATCH=y
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
CONFIG_NET_ACT_BPF=m
|
||||
CONFIG_NET_ACT_MIRRED=m
|
||||
CONFIG_NET_CLS_U32=m
|
||||
CONFIG_NET_ACT_BPF=m
|
||||
CONFIG_OPENVSWITCH=m
|
||||
CONFIG_VSOCKETS=m
|
||||
CONFIG_VIRTIO_VSOCKETS=m
|
||||
|
|
@ -322,6 +323,7 @@ CONFIG_PATA_SCH=y
|
|||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=y
|
||||
CONFIG_DM_SNAPSHOT=y
|
||||
CONFIG_DM_THIN_PROVISIONING=y
|
||||
CONFIG_DM_MIRROR=y
|
||||
|
|
@ -342,7 +344,6 @@ CONFIG_IPVLAN=m
|
|||
CONFIG_VXLAN=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_TUN=y
|
||||
CONFIG_TAP=y
|
||||
CONFIG_VETH=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_AMD8111_ETH=m
|
||||
|
|
@ -439,7 +440,6 @@ CONFIG_EEEPC_LAPTOP=y
|
|||
CONFIG_AMD_IOMMU=y
|
||||
CONFIG_INTEL_IOMMU=y
|
||||
# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
|
||||
CONFIG_EFI_VARS=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
|
|
@ -480,8 +480,16 @@ CONFIG_NLS_CODEPAGE_437=y
|
|||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
|
||||
CONFIG_SECURITY_SELINUX_DISABLE=y
|
||||
CONFIG_CRYPTO_XTS=y
|
||||
CONFIG_CRYPTO_AES_NI_INTEL=y
|
||||
CONFIG_CRYPTO_USER_API_HASH=y
|
||||
CONFIG_CRYPTO_USER_API_SKCIPHER=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
# CONFIG_UNUSED_SYMBOLS is not set
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
|
|
@ -494,15 +502,3 @@ CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
|
|||
CONFIG_EARLY_PRINTK_DBGP=y
|
||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||
CONFIG_OPTIMIZE_INLINING=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
|
||||
CONFIG_SECURITY_SELINUX_DISABLE=y
|
||||
CONFIG_CRYPTO_USER_API_HASH=y
|
||||
CONFIG_KVM=m
|
||||
CONFIG_KVM_INTEL=m
|
||||
CONFIG_KVM_AMD=m
|
||||
CONFIG_VHOST_NET=m
|
||||
CONFIG_VHOST=m
|
||||
CONFIG_VHOST_VSOCK=m
|
||||
|
|
|
|||
|
|
@ -60,3 +60,6 @@ BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="$(BR2_EXTERNAL_MINIKUBE_PATH)/board/coreos/
|
|||
BR2_TARGET_SYSLINUX=y
|
||||
BR2_PACKAGE_HOST_E2TOOLS=y
|
||||
BR2_PACKAGE_SYSTEMD_TIMESYNCD=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_SYSSTAT=y
|
||||
BR2_PACKAGE_HTOP=y
|
||||
|
|
|
|||
|
|
@ -1,4 +1,20 @@
|
|||
[
|
||||
{
|
||||
"name": "v1.6.1",
|
||||
"checksums": {
|
||||
"darwin": "bcfc181ade08bd2a87fca70f0aa59f9f4b23c893fc2b335b3cb8f05b84ae2d34",
|
||||
"linux": "cbd526d64531266d42f02667339d3c53e5a399e3abebda63c96b0bbd6b7e935d",
|
||||
"windows": "1d7372fcf099d583d4140a4ce4aa8f5c2752d3bd0d143e53647aee6221dcb663"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1.6.0",
|
||||
"checksums": {
|
||||
"darwin": "fd1af02f0fc11fb0bec35b9ae1f6bf2d157f51948155d8b1ddc899521642fc32",
|
||||
"linux": "48738607ecdb0b00815599230a2a2b17dc90bd3bbcb1b217bace043f78370db3",
|
||||
"windows": "20e7db220308f06913acd10addb1ec01c87b74245cebc70fa18a979c1b323f34"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1.5.2",
|
||||
"checksums": {
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ if [[ "${LOAD}" -gt 2 ]]; then
|
|||
uptime
|
||||
fi
|
||||
|
||||
e2e_start_time="$(date -u +%s)"
|
||||
echo ""
|
||||
echo ">> Starting ${E2E_BIN} at $(date)"
|
||||
set -x
|
||||
|
|
@ -279,9 +280,19 @@ else
|
|||
echo "minikube: FAIL"
|
||||
fi
|
||||
|
||||
## caclucate the time took to finish running e2e binary test.
|
||||
e2e_end_time="$(date -u +%s)"
|
||||
elapsed=$(($e2e_end_time-$e2e_start_time))
|
||||
min=$(($elapsed/60))
|
||||
sec=$(tail -c 3 <<< $((${elapsed}00/60)))
|
||||
elapsed=$min.$sec
|
||||
description="completed with ${status} in ${elapsed} minute(s)."
|
||||
echo $description
|
||||
|
||||
|
||||
echo ">> Cleaning up after ourselves ..."
|
||||
${SUDO_PREFIX}${MINIKUBE_BIN} tunnel --cleanup || true
|
||||
${SUDO_PREFIX}${MINIKUBE_BIN} delete >/dev/null 2>/dev/null || true
|
||||
${SUDO_PREFIX}${MINIKUBE_BIN} delete --all >/dev/null 2>/dev/null || true
|
||||
cleanup_stale_routes || true
|
||||
|
||||
${SUDO_PREFIX} rm -Rf "${MINIKUBE_HOME}" || true
|
||||
|
|
@ -300,6 +311,7 @@ function retry_github_status() {
|
|||
local state=$3
|
||||
local token=$4
|
||||
local target=$5
|
||||
local desc=$6
|
||||
|
||||
# Retry in case we hit our GitHub API quota or fail other ways.
|
||||
local attempt=0
|
||||
|
|
@ -312,7 +324,7 @@ function retry_github_status() {
|
|||
"https://api.github.com/repos/kubernetes/minikube/statuses/${commit}?access_token=${token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST \
|
||||
-d "{\"state\": \"${state}\", \"description\": \"Jenkins\", \"target_url\": \"${target}\", \"context\": \"${context}\"}" || echo 999)
|
||||
-d "{\"state\": \"${state}\", \"description\": \"Jenkins: ${desc}\", \"target_url\": \"${target}\", \"context\": \"${context}\"}" || echo 999)
|
||||
|
||||
# 2xx HTTP codes
|
||||
if [[ "${code}" =~ ^2 ]]; then
|
||||
|
|
@ -327,5 +339,7 @@ function retry_github_status() {
|
|||
done
|
||||
}
|
||||
|
||||
retry_github_status "${COMMIT}" "${JOB_NAME}" "${status}" "${access_token}" "https://storage.googleapis.com/minikube-builds/logs/${MINIKUBE_LOCATION}/${JOB_NAME}.txt"
|
||||
|
||||
|
||||
retry_github_status "${COMMIT}" "${JOB_NAME}" "${status}" "${access_token}" "https://storage.googleapis.com/minikube-builds/logs/${MINIKUBE_LOCATION}/${JOB_NAME}.txt" "${description}"
|
||||
exit $result
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ if ! [[ -x "${DIR}/release-notes" ]]; then
|
|||
install_release_notes_helper
|
||||
fi
|
||||
|
||||
"${DIR}/release-notes" kubernetes minikube
|
||||
git pull git@github.com:kubernetes/minikube master --tags
|
||||
recent=$(git describe --abbrev=0)
|
||||
|
||||
"${DIR}/release-notes" kubernetes minikube --since $recent
|
||||
|
||||
echo "Huge thank you for this release towards our contributors: "
|
||||
git log "$(git describe --abbrev=0)".. --format="%aN" --reverse | sort | uniq | awk '{printf "- %s\n", $0 }'
|
||||
git log "$recent".. --format="%aN" --reverse | sort | uniq | awk '{printf "- %s\n", $0 }'
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const (
|
|||
containerdConfigTomlPath = "/etc/containerd/config.toml"
|
||||
storedContainerdConfigTomlPath = "/tmp/config.toml"
|
||||
gvisorContainerdShimURL = "https://github.com/google/gvisor-containerd-shim/releases/download/v0.0.3/containerd-shim-runsc-v1.linux-amd64"
|
||||
gvisorURL = "https://storage.googleapis.com/gvisor/releases/nightly/2019-01-14/runsc"
|
||||
gvisorURL = "https://storage.googleapis.com/gvisor/releases/nightly/2019-11-27/runsc"
|
||||
)
|
||||
|
||||
// Enable follows these steps for enabling gvisor in minikube:
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type Bootstrapper interface {
|
|||
// PullImages pulls images necessary for a cluster. Success should not be required.
|
||||
PullImages(config.KubernetesConfig) error
|
||||
StartCluster(config.KubernetesConfig) error
|
||||
UpdateCluster(config.KubernetesConfig) error
|
||||
UpdateCluster(config.MachineConfig) error
|
||||
DeleteCluster(config.KubernetesConfig) error
|
||||
WaitForCluster(config.KubernetesConfig, time.Duration) error
|
||||
// LogCommands returns a map of log type to a command which will display that log.
|
||||
|
|
@ -64,12 +64,11 @@ func GetCachedBinaryList(bootstrapper string) []string {
|
|||
}
|
||||
|
||||
// GetCachedImageList returns the list of images for a version
|
||||
func GetCachedImageList(imageRepository string, version string, bootstrapper string) []string {
|
||||
func GetCachedImageList(imageRepository string, version string, bootstrapper string) ([]string, error) {
|
||||
switch bootstrapper {
|
||||
case BootstrapperTypeKubeadm:
|
||||
images := images.CachedImages(imageRepository, version)
|
||||
return images
|
||||
return images.Kubeadm(imageRepository, version)
|
||||
default:
|
||||
return []string{}
|
||||
return []string{}, nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -40,8 +39,8 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/lock"
|
||||
|
||||
"github.com/juju/clock"
|
||||
"github.com/juju/mutex"
|
||||
)
|
||||
|
||||
|
|
@ -61,17 +60,17 @@ var (
|
|||
|
||||
// SetupCerts gets the generated credentials required to talk to the APIServer.
|
||||
func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
|
||||
|
||||
localPath := localpath.MiniPath()
|
||||
glog.Infof("Setting up %s for IP: %s\n", localPath, k8s.NodeIP)
|
||||
|
||||
// WARNING: This function was not designed for multiple profiles, so it is VERY racey:
|
||||
//
|
||||
// It updates a shared certificate file and uploads it to the apiserver before launch.
|
||||
//
|
||||
// If another process updates the shared certificate, it's invalid.
|
||||
// TODO: Instead of racey manipulation of a shared certificate, use per-profile certs
|
||||
spec := mutex.Spec{
|
||||
Name: "setupCerts",
|
||||
Clock: clock.WallClock,
|
||||
Delay: 15 * time.Second,
|
||||
}
|
||||
spec := lock.PathMutexSpec(filepath.Join(localPath, "certs"))
|
||||
glog.Infof("acquiring lock: %+v", spec)
|
||||
releaser, err := mutex.Acquire(spec)
|
||||
if err != nil {
|
||||
|
|
@ -79,9 +78,6 @@ func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
|
|||
}
|
||||
defer releaser.Release()
|
||||
|
||||
localPath := localpath.MiniPath()
|
||||
glog.Infof("Setting up %s for IP: %s\n", localPath, k8s.NodeIP)
|
||||
|
||||
if err := generateCerts(k8s); err != nil {
|
||||
return errors.Wrap(err, "Error generating certs")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,186 +14,63 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package images implements helpers for getting image names
|
||||
package images
|
||||
|
||||
import (
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/golang/glog"
|
||||
minikubeVersion "k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultImageRepo is the default repository for images
|
||||
DefaultImageRepo = "k8s.gcr.io"
|
||||
// DefaultMinikubeRepo is the default repository for minikube
|
||||
DefaultMinikubeRepo = "gcr.io/k8s-minikube"
|
||||
)
|
||||
|
||||
// getImageRepositories returns either the k8s image registry on GCR or a mirror if specified
|
||||
func getImageRepository(imageRepository string) string {
|
||||
if imageRepository == "" {
|
||||
imageRepository = DefaultImageRepo
|
||||
}
|
||||
if !strings.HasSuffix(imageRepository, "/") {
|
||||
imageRepository += "/"
|
||||
}
|
||||
|
||||
return imageRepository
|
||||
}
|
||||
|
||||
// getMinikubeRepository returns either the minikube image registry on GCR or a mirror if specified
|
||||
func getMinikubeRepository(imageRepository string) string {
|
||||
minikubeRepository := imageRepository
|
||||
if minikubeRepository == "" {
|
||||
minikubeRepository = DefaultMinikubeRepo
|
||||
}
|
||||
if !strings.HasSuffix(minikubeRepository, "/") {
|
||||
minikubeRepository += "/"
|
||||
}
|
||||
|
||||
return minikubeRepository
|
||||
}
|
||||
|
||||
// CachedImages gets the images to cache for kubeadm for a version
|
||||
func CachedImages(imageRepositoryStr string, kubernetesVersionStr string) []string {
|
||||
imageRepository := getImageRepository(imageRepositoryStr)
|
||||
minikubeRepository := getMinikubeRepository(imageRepositoryStr)
|
||||
|
||||
v1_16plus := semver.MustParseRange(">=1.16.0")
|
||||
v1_14plus := semver.MustParseRange(">=1.14.0 <1.16.0")
|
||||
v1_13 := semver.MustParseRange(">=1.13.0 <1.14.0")
|
||||
v1_12 := semver.MustParseRange(">=1.12.0 <1.13.0")
|
||||
v1_11 := semver.MustParseRange(">=1.11.0 <1.12.0")
|
||||
v1_12plus := semver.MustParseRange(">=1.12.0")
|
||||
|
||||
kubernetesVersion, err := semver.Make(strings.TrimPrefix(kubernetesVersionStr, minikubeVersion.VersionPrefix))
|
||||
if err != nil {
|
||||
glog.Errorln("Error parsing version semver: ", err)
|
||||
}
|
||||
|
||||
var images []string
|
||||
if v1_12plus(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
imageRepository + "kube-proxy" + ArchTag(false) + kubernetesVersionStr,
|
||||
imageRepository + "kube-scheduler" + ArchTag(false) + kubernetesVersionStr,
|
||||
imageRepository + "kube-controller-manager" + ArchTag(false) + kubernetesVersionStr,
|
||||
imageRepository + "kube-apiserver" + ArchTag(false) + kubernetesVersionStr,
|
||||
}...)
|
||||
} else {
|
||||
images = append(images, []string{
|
||||
imageRepository + "kube-proxy" + ArchTag(true) + kubernetesVersionStr,
|
||||
imageRepository + "kube-scheduler" + ArchTag(true) + kubernetesVersionStr,
|
||||
imageRepository + "kube-controller-manager" + ArchTag(true) + kubernetesVersionStr,
|
||||
imageRepository + "kube-apiserver" + ArchTag(true) + kubernetesVersionStr,
|
||||
}...)
|
||||
}
|
||||
|
||||
podInfraContainerImage := PauseImage(imageRepository, kubernetesVersionStr)
|
||||
if v1_16plus(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
podInfraContainerImage,
|
||||
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "etcd" + ArchTag(false) + "3.3.15-0",
|
||||
imageRepository + "coredns" + ArchTag(false) + "1.6.2",
|
||||
}...)
|
||||
|
||||
} else if v1_14plus(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
podInfraContainerImage,
|
||||
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.13",
|
||||
imageRepository + "etcd" + ArchTag(false) + "3.3.10",
|
||||
imageRepository + "coredns" + ArchTag(false) + "1.3.1",
|
||||
}...)
|
||||
|
||||
} else if v1_13(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
podInfraContainerImage,
|
||||
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "etcd" + ArchTag(false) + "3.2.24",
|
||||
imageRepository + "coredns:1.2.6",
|
||||
}...)
|
||||
|
||||
} else if v1_12(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
podInfraContainerImage,
|
||||
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "etcd" + ArchTag(false) + "3.2.24",
|
||||
imageRepository + "coredns:1.2.2",
|
||||
}...)
|
||||
|
||||
} else if v1_11(kubernetesVersion) {
|
||||
images = append(images, []string{
|
||||
podInfraContainerImage,
|
||||
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
|
||||
imageRepository + "etcd" + ArchTag(true) + "3.2.18",
|
||||
imageRepository + "coredns:1.1.3",
|
||||
}...)
|
||||
}
|
||||
|
||||
images = append(images, []string{
|
||||
imageRepository + "kube-addon-manager" + ArchTag(false) + "v9.0",
|
||||
minikubeRepository + "storage-provisioner" + ArchTag(false) + "v1.8.1",
|
||||
}...)
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
// PauseImage returns the image name for pause image (for pod infra)
|
||||
func PauseImage(imageRepositoryStr string, kubernetesVersionStr string) string {
|
||||
imageRepository := getImageRepository(imageRepositoryStr)
|
||||
|
||||
v1_16plus := semver.MustParseRange(">=1.16.0")
|
||||
v1_14plus := semver.MustParseRange(">=1.14.0 <1.16.0")
|
||||
v1_13 := semver.MustParseRange(">=1.13.0 <1.14.0")
|
||||
v1_12 := semver.MustParseRange(">=1.12.0 <1.13.0")
|
||||
v1_11 := semver.MustParseRange(">=1.11.0 <1.12.0")
|
||||
|
||||
kubernetesVersion, err := semver.Make(strings.TrimPrefix(kubernetesVersionStr, minikubeVersion.VersionPrefix))
|
||||
if err != nil {
|
||||
glog.Errorln("Error parsing version semver: ", err)
|
||||
}
|
||||
|
||||
var podInfraContainerImage string
|
||||
switch {
|
||||
case v1_16plus(kubernetesVersion):
|
||||
podInfraContainerImage = imageRepository + "pause:3.1"
|
||||
|
||||
case v1_14plus(kubernetesVersion):
|
||||
podInfraContainerImage = imageRepository + "pause:3.1"
|
||||
|
||||
case v1_13(kubernetesVersion):
|
||||
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.1"
|
||||
|
||||
case v1_12(kubernetesVersion):
|
||||
podInfraContainerImage = imageRepository + "pause:3.1"
|
||||
|
||||
case v1_11(kubernetesVersion):
|
||||
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.1"
|
||||
|
||||
default:
|
||||
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.0"
|
||||
}
|
||||
|
||||
return podInfraContainerImage
|
||||
}
|
||||
|
||||
// ArchTag returns the archtag for images
|
||||
// ArchTag returns a CPU architecture suffix for images
|
||||
func ArchTag(hasTag bool) string {
|
||||
if runtime.GOARCH == "amd64" && !hasTag {
|
||||
return ":"
|
||||
}
|
||||
return "-" + runtime.GOARCH + ":"
|
||||
}
|
||||
|
||||
// Auxiliary returns images that are helpful for running minikube
|
||||
func Auxiliary(mirror string) []string {
|
||||
return []string{
|
||||
addonManager(mirror),
|
||||
storageProvisioner(mirror),
|
||||
dashboardFrontend(mirror),
|
||||
dashboardMetrics(mirror),
|
||||
}
|
||||
}
|
||||
|
||||
// Pause returns the image name to pull for the pause image
|
||||
func Pause(mirror string) string {
|
||||
// Should match `PauseVersion` in:
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
return path.Join(KubernetesRepo(mirror), "pause"+ArchTag(false)+"3.1")
|
||||
}
|
||||
|
||||
// storageProvisioner returns the minikube storage provisioner image
|
||||
func storageProvisioner(mirror string) string {
|
||||
return path.Join(minikubeRepo(mirror), "storage-provisioner"+ArchTag(false)+"v1.8.1")
|
||||
}
|
||||
|
||||
// addonManager returns the Kubernetes addon manager image
|
||||
func addonManager(mirror string) string {
|
||||
return path.Join(KubernetesRepo(mirror), "kube-addon-manager"+ArchTag(false)+"v9.0.2")
|
||||
}
|
||||
|
||||
// dashboardFrontend returns the image used for the dashboard frontend
|
||||
func dashboardFrontend(repo string) string {
|
||||
if repo == "" {
|
||||
repo = "kubernetesui"
|
||||
}
|
||||
// See 'kubernetes-dashboard' in deploy/addons/dashboard/dashboard-dp.yaml
|
||||
return path.Join(repo, "dashboard:v2.0.0-beta8")
|
||||
}
|
||||
|
||||
// dashboardMetrics returns the image used for the dashboard metrics scraper
|
||||
func dashboardMetrics(repo string) string {
|
||||
if repo == "" {
|
||||
repo = "kubernetesui"
|
||||
}
|
||||
// See 'dashboard-metrics-scraper' in deploy/addons/dashboard/dashboard-dp.yaml
|
||||
return path.Join(repo, "metrics-scraper:v1.0.2")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestAuxiliary(t *testing.T) {
|
||||
want := []string{
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}
|
||||
got := Auxiliary("")
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("images mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuxiliaryMirror(t *testing.T) {
|
||||
want := []string{
|
||||
"test.mirror/kube-addon-manager:v9.0.2",
|
||||
"test.mirror/storage-provisioner:v1.8.1",
|
||||
"test.mirror/dashboard:v2.0.0-beta8",
|
||||
"test.mirror/metrics-scraper:v1.0.2",
|
||||
}
|
||||
got := Auxiliary("test.mirror")
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("images mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Kubeadm returns a list of images necessary to bootstrap kubeadm
|
||||
func Kubeadm(mirror string, version string) ([]string, error) {
|
||||
v, err := semver.Make(strings.TrimPrefix(version, "v"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "semver")
|
||||
}
|
||||
|
||||
imgs := []string{
|
||||
componentImage("kube-proxy", v, mirror),
|
||||
componentImage("kube-scheduler", v, mirror),
|
||||
componentImage("kube-controller-manager", v, mirror),
|
||||
componentImage("kube-apiserver", v, mirror),
|
||||
coreDNS(v, mirror),
|
||||
etcd(v, mirror),
|
||||
Pause(mirror),
|
||||
}
|
||||
imgs = append(imgs, Auxiliary(mirror)...)
|
||||
return imgs, nil
|
||||
}
|
||||
|
||||
// componentImage returns a Kubernetes component image to pull
|
||||
func componentImage(name string, v semver.Version, mirror string) string {
|
||||
needsArchSuffix := false
|
||||
ancient := semver.MustParseRange("<1.12.0")
|
||||
if ancient(v) {
|
||||
needsArchSuffix = true
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%sv%s", path.Join(KubernetesRepo(mirror), name+ArchTag(needsArchSuffix)), v)
|
||||
}
|
||||
|
||||
// coreDNS returns the images used for CoreDNS
|
||||
func coreDNS(v semver.Version, mirror string) string {
|
||||
// Should match `CoreDNSVersion` in
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
cv := "1.6.5"
|
||||
switch v.Minor {
|
||||
case 16:
|
||||
cv = "1.6.2"
|
||||
case 15, 14:
|
||||
cv = "1.3.1"
|
||||
case 13:
|
||||
cv = "1.2.6"
|
||||
case 12:
|
||||
cv = "1.2.2"
|
||||
case 11:
|
||||
cv = "1.1.3"
|
||||
}
|
||||
return path.Join(KubernetesRepo(mirror), "coredns"+ArchTag(false)+cv)
|
||||
}
|
||||
|
||||
// etcd returns the image used for etcd
|
||||
func etcd(v semver.Version, mirror string) string {
|
||||
needsArchSuffix := false
|
||||
ancient := semver.MustParseRange("<1.12.0")
|
||||
if ancient(v) {
|
||||
needsArchSuffix = true
|
||||
}
|
||||
|
||||
// Should match `DefaultEtcdVersion` in:
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
|
||||
ev := "3.4.3-0"
|
||||
switch v.Minor {
|
||||
case 16:
|
||||
ev = "3.3.15-0"
|
||||
case 14, 15:
|
||||
ev = "3.3.10"
|
||||
case 12, 13:
|
||||
ev = "3.2.24"
|
||||
case 11:
|
||||
ev = "3.2.18"
|
||||
}
|
||||
return path.Join(KubernetesRepo(mirror), "etcd"+ArchTag(needsArchSuffix)+ev)
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestKubeadmImages(t *testing.T) {
|
||||
tests := []struct {
|
||||
version string
|
||||
mirror string
|
||||
want []string
|
||||
}{
|
||||
{"v1.17.0", "", []string{
|
||||
"k8s.gcr.io/kube-proxy:v1.17.0",
|
||||
"k8s.gcr.io/kube-scheduler:v1.17.0",
|
||||
"k8s.gcr.io/kube-controller-manager:v1.17.0",
|
||||
"k8s.gcr.io/kube-apiserver:v1.17.0",
|
||||
"k8s.gcr.io/coredns:1.6.5",
|
||||
"k8s.gcr.io/etcd:3.4.3-0",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.16.1", "mirror.k8s.io", []string{
|
||||
"mirror.k8s.io/kube-proxy:v1.16.1",
|
||||
"mirror.k8s.io/kube-scheduler:v1.16.1",
|
||||
"mirror.k8s.io/kube-controller-manager:v1.16.1",
|
||||
"mirror.k8s.io/kube-apiserver:v1.16.1",
|
||||
"mirror.k8s.io/coredns:1.6.2",
|
||||
"mirror.k8s.io/etcd:3.3.15-0",
|
||||
"mirror.k8s.io/pause:3.1",
|
||||
"mirror.k8s.io/kube-addon-manager:v9.0.2",
|
||||
"mirror.k8s.io/storage-provisioner:v1.8.1",
|
||||
"mirror.k8s.io/dashboard:v2.0.0-beta8",
|
||||
"mirror.k8s.io/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.15.0", "", []string{
|
||||
"k8s.gcr.io/kube-proxy:v1.15.0",
|
||||
"k8s.gcr.io/kube-scheduler:v1.15.0",
|
||||
"k8s.gcr.io/kube-controller-manager:v1.15.0",
|
||||
"k8s.gcr.io/kube-apiserver:v1.15.0",
|
||||
"k8s.gcr.io/coredns:1.3.1",
|
||||
"k8s.gcr.io/etcd:3.3.10",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.14.0", "", []string{
|
||||
"k8s.gcr.io/kube-proxy:v1.14.0",
|
||||
"k8s.gcr.io/kube-scheduler:v1.14.0",
|
||||
"k8s.gcr.io/kube-controller-manager:v1.14.0",
|
||||
"k8s.gcr.io/kube-apiserver:v1.14.0",
|
||||
"k8s.gcr.io/coredns:1.3.1",
|
||||
"k8s.gcr.io/etcd:3.3.10",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.13.0", "", []string{
|
||||
"k8s.gcr.io/kube-proxy:v1.13.0",
|
||||
"k8s.gcr.io/kube-scheduler:v1.13.0",
|
||||
"k8s.gcr.io/kube-controller-manager:v1.13.0",
|
||||
"k8s.gcr.io/kube-apiserver:v1.13.0",
|
||||
"k8s.gcr.io/coredns:1.2.6",
|
||||
"k8s.gcr.io/etcd:3.2.24",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.12.0", "", []string{
|
||||
"k8s.gcr.io/kube-proxy:v1.12.0",
|
||||
"k8s.gcr.io/kube-scheduler:v1.12.0",
|
||||
"k8s.gcr.io/kube-controller-manager:v1.12.0",
|
||||
"k8s.gcr.io/kube-apiserver:v1.12.0",
|
||||
"k8s.gcr.io/coredns:1.2.2",
|
||||
"k8s.gcr.io/etcd:3.2.24",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
{"v1.11.10", "", []string{
|
||||
"k8s.gcr.io/kube-proxy-amd64:v1.11.10",
|
||||
"k8s.gcr.io/kube-scheduler-amd64:v1.11.10",
|
||||
"k8s.gcr.io/kube-controller-manager-amd64:v1.11.10",
|
||||
"k8s.gcr.io/kube-apiserver-amd64:v1.11.10",
|
||||
"k8s.gcr.io/coredns:1.1.3",
|
||||
"k8s.gcr.io/etcd-amd64:3.2.18",
|
||||
"k8s.gcr.io/pause:3.1",
|
||||
"k8s.gcr.io/kube-addon-manager:v9.0.2",
|
||||
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
|
||||
"kubernetesui/dashboard:v2.0.0-beta8",
|
||||
"kubernetesui/metrics-scraper:v1.0.2",
|
||||
}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
got, err := Kubeadm(tc.mirror, tc.version)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
sort.Strings(got)
|
||||
sort.Strings(tc.want)
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Errorf("%s images mismatch (-want +got):\n%s", tc.version, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
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 images
|
||||
|
||||
// DefaultKubernetesRepo is the default Kubernetes repository
|
||||
const DefaultKubernetesRepo = "k8s.gcr.io"
|
||||
|
||||
// KubernetesRepo returns the official Kubernetes repository, or an alternate
|
||||
func KubernetesRepo(mirror string) string {
|
||||
if mirror != "" {
|
||||
return mirror
|
||||
}
|
||||
return DefaultKubernetesRepo
|
||||
}
|
||||
|
||||
// minikubeRepo returns the official minikube repository, or an alternate
|
||||
func minikubeRepo(mirror string) string {
|
||||
if mirror != "" {
|
||||
return mirror
|
||||
}
|
||||
return "gcr.io/k8s-minikube"
|
||||
}
|
||||
|
|
@ -596,7 +596,7 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte,
|
|||
extraOpts["node-ip"] = k8s.NodeIP
|
||||
}
|
||||
|
||||
pauseImage := images.PauseImage(k8s.ImageRepository, k8s.KubernetesVersion)
|
||||
pauseImage := images.Pause(k8s.ImageRepository)
|
||||
if _, ok := extraOpts["pod-infra-container-image"]; !ok && k8s.ImageRepository != "" && pauseImage != "" && k8s.ContainerRuntime != remoteContainerRuntime {
|
||||
extraOpts["pod-infra-container-image"] = pauseImage
|
||||
}
|
||||
|
|
@ -629,33 +629,37 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte,
|
|||
}
|
||||
|
||||
// UpdateCluster updates the cluster
|
||||
func (k *Bootstrapper) UpdateCluster(cfg config.KubernetesConfig) error {
|
||||
images := images.CachedImages(cfg.ImageRepository, cfg.KubernetesVersion)
|
||||
if cfg.ShouldLoadCachedImages {
|
||||
if err := machine.LoadImages(k.c, images, constants.ImageCacheDir); err != nil {
|
||||
func (k *Bootstrapper) UpdateCluster(cfg config.MachineConfig) error {
|
||||
images, err := images.Kubeadm(cfg.KubernetesConfig.ImageRepository, cfg.KubernetesConfig.KubernetesVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "kubeadm images")
|
||||
}
|
||||
|
||||
if cfg.KubernetesConfig.ShouldLoadCachedImages {
|
||||
if err := machine.LoadImages(&cfg, k.c, images, constants.ImageCacheDir); err != nil {
|
||||
out.FailureT("Unable to load cached images: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
}
|
||||
r, err := cruntime.New(cruntime.Config{Type: cfg.ContainerRuntime, Socket: cfg.CRISocket})
|
||||
r, err := cruntime.New(cruntime.Config{Type: cfg.ContainerRuntime, Socket: cfg.KubernetesConfig.CRISocket})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "runtime")
|
||||
}
|
||||
kubeadmCfg, err := generateConfig(cfg, r)
|
||||
kubeadmCfg, err := generateConfig(cfg.KubernetesConfig, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating kubeadm cfg")
|
||||
}
|
||||
|
||||
kubeletCfg, err := NewKubeletConfig(cfg, r)
|
||||
kubeletCfg, err := NewKubeletConfig(cfg.KubernetesConfig, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating kubelet config")
|
||||
}
|
||||
|
||||
kubeletService, err := NewKubeletService(cfg)
|
||||
kubeletService, err := NewKubeletService(cfg.KubernetesConfig)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating kubelet service")
|
||||
}
|
||||
|
||||
glog.Infof("kubelet %s config:\n%s", cfg.KubernetesVersion, kubeletCfg)
|
||||
glog.Infof("kubelet %s config:\n%+v", kubeletCfg, cfg.KubernetesConfig)
|
||||
|
||||
stopCmd := exec.Command("/bin/bash", "-c", "pgrep kubelet && sudo systemctl stop kubelet")
|
||||
// stop kubelet to avoid "Text File Busy" error
|
||||
|
|
@ -663,11 +667,11 @@ func (k *Bootstrapper) UpdateCluster(cfg config.KubernetesConfig) error {
|
|||
glog.Warningf("unable to stop kubelet: %s command: %q output: %q", err, rr.Command(), rr.Output())
|
||||
}
|
||||
|
||||
if err := transferBinaries(cfg, k.c); err != nil {
|
||||
if err := transferBinaries(cfg.KubernetesConfig, k.c); err != nil {
|
||||
return errors.Wrap(err, "downloading binaries")
|
||||
}
|
||||
files := configFiles(cfg, kubeadmCfg, kubeletCfg, kubeletService)
|
||||
if err := addAddons(&files, assets.GenerateTemplateData(cfg)); err != nil {
|
||||
files := configFiles(cfg.KubernetesConfig, kubeadmCfg, kubeletCfg, kubeletService)
|
||||
if err := addAddons(&files, assets.GenerateTemplateData(cfg.KubernetesConfig)); err != nil {
|
||||
return errors.Wrap(err, "adding addons")
|
||||
}
|
||||
for _, f := range files {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ Wants=crio.service
|
|||
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0-rc.1/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=/var/run/crio/crio.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=/var/run/crio/crio.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
|
||||
[Install]
|
||||
`,
|
||||
|
|
@ -84,7 +84,7 @@ Wants=containerd.service
|
|||
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0-rc.1/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=unix:///run/containerd/containerd.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=unix:///run/containerd/containerd.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
|
||||
[Install]
|
||||
`,
|
||||
|
|
@ -109,7 +109,7 @@ Wants=containerd.service
|
|||
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0-rc.1/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=unix:///run/containerd/containerd.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.200 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=unix:///run/containerd/containerd.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.200 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m
|
||||
|
||||
[Install]
|
||||
`,
|
||||
|
|
@ -128,7 +128,7 @@ Wants=docker.socket
|
|||
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0-rc.1/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=docker --fail-swap-on=false --hostname-override=minikube --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-infra-container-image=docker-proxy-image.io/google_containers/pause:3.1 --pod-manifest-path=/etc/kubernetes/manifests
|
||||
ExecStart=/var/lib/minikube/binaries/v1.17.0/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=docker --fail-swap-on=false --hostname-override=minikube --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-infra-container-image=docker-proxy-image.io/google_containers/pause:3.1 --pod-manifest-path=/etc/kubernetes/manifests
|
||||
|
||||
[Install]
|
||||
`,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
)
|
||||
|
||||
|
|
@ -124,9 +123,8 @@ func encode(w io.Writer, m MinikubeConfig) error {
|
|||
}
|
||||
|
||||
// Load loads the kubernetes and machine config for the current machine
|
||||
func Load() (*MachineConfig, error) {
|
||||
machine := viper.GetString(MachineProfile)
|
||||
return DefaultLoader.LoadConfigFromFile(machine)
|
||||
func Load(profile string) (*MachineConfig, error) {
|
||||
return DefaultLoader.LoadConfigFromFile(profile)
|
||||
}
|
||||
|
||||
// Loader loads the kubernetes and machine config based on the machine profile name
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func CreateProfile(name string, cfg *MachineConfig, miniHome ...string) error {
|
|||
}
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
if err = lock.WriteFile(tf.Name(), data, 0600); err != nil {
|
||||
if err = ioutil.WriteFile(tf.Name(), data, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
// Profile represents a minikube profile
|
||||
type Profile struct {
|
||||
Name string
|
||||
Status string // running, stopped
|
||||
Config []*MachineConfig
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ var DefaultISOURL = fmt.Sprintf("https://storage.googleapis.com/%s/minikube-%s.i
|
|||
var DefaultISOSHAURL = DefaultISOURL + SHASuffix
|
||||
|
||||
// DefaultKubernetesVersion is the default kubernetes version
|
||||
var DefaultKubernetesVersion = "v1.17.0-rc.1"
|
||||
var DefaultKubernetesVersion = "v1.17.0"
|
||||
|
||||
// NewestKubernetesVersion is the newest Kubernetes version to test against
|
||||
var NewestKubernetesVersion = "v1.17.0-rc.1"
|
||||
var NewestKubernetesVersion = "v1.17.0"
|
||||
|
||||
// OldestKubernetesVersion is the oldest Kubernetes version to test against
|
||||
var OldestKubernetesVersion = "v1.11.10"
|
||||
|
|
|
|||
|
|
@ -169,13 +169,13 @@ func (r *Containerd) Available() error {
|
|||
}
|
||||
|
||||
// generateContainerdConfig sets up /etc/containerd/config.toml
|
||||
func generateContainerdConfig(cr CommandRunner, imageRepository string, k8sVersion string) error {
|
||||
func generateContainerdConfig(cr CommandRunner, imageRepository string) error {
|
||||
cPath := containerdConfigFile
|
||||
t, err := template.New("containerd.config.toml").Parse(containerdConfigTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pauseImage := images.PauseImage(imageRepository, k8sVersion)
|
||||
pauseImage := images.Pause(imageRepository)
|
||||
opts := struct{ PodInfraContainerImage string }{PodInfraContainerImage: pauseImage}
|
||||
var b bytes.Buffer
|
||||
if err := t.Execute(&b, opts); err != nil {
|
||||
|
|
@ -198,7 +198,7 @@ func (r *Containerd) Enable(disOthers bool) error {
|
|||
if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := generateContainerdConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil {
|
||||
if err := generateContainerdConfig(r.Runner, r.ImageRepository); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := enableIPForwarding(r.Runner); err != nil {
|
||||
|
|
@ -221,6 +221,15 @@ func (r *Containerd) Disable() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists, expected input format
|
||||
func (r *Containerd) ImageExists(name string, sha string) bool {
|
||||
c := exec.Command("/bin/bash", "-c", fmt.Sprintf("sudo ctr -n=k8s.io images check | grep %s | grep %s", name, sha))
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *Containerd) LoadImage(path string) error {
|
||||
glog.Infof("Loading image: %s", path)
|
||||
|
|
|
|||
|
|
@ -407,13 +407,13 @@ image-endpoint: unix://{{.Socket}}
|
|||
}
|
||||
|
||||
// generateCRIOConfig sets up /etc/crio/crio.conf
|
||||
func generateCRIOConfig(cr CommandRunner, imageRepository string, k8sVersion string) error {
|
||||
func generateCRIOConfig(cr CommandRunner, imageRepository string) error {
|
||||
cPath := crioConfigFile
|
||||
t, err := template.New("crio.conf").Parse(crioConfigTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pauseImage := images.PauseImage(imageRepository, k8sVersion)
|
||||
pauseImage := images.Pause(imageRepository)
|
||||
opts := struct{ PodInfraContainerImage string }{PodInfraContainerImage: pauseImage}
|
||||
var b bytes.Buffer
|
||||
if err := t.Execute(&b, opts); err != nil {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (r *CRIO) Enable(disOthers bool) error {
|
|||
if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := generateCRIOConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil {
|
||||
if err := generateCRIOConfig(r.Runner, r.ImageRepository); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := enableIPForwarding(r.Runner); err != nil {
|
||||
|
|
@ -119,6 +119,20 @@ func (r *CRIO) Disable() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists
|
||||
func (r *CRIO) ImageExists(name string, sha string) bool {
|
||||
// expected output looks like [NAME@sha256:SHA]
|
||||
c := exec.Command("sudo", "podman", "inspect", "--format='{{.Id}}'", name)
|
||||
rr, err := r.Runner.RunCmd(c)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if !strings.Contains(rr.Output(), sha) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *CRIO) LoadImage(path string) error {
|
||||
glog.Infof("Loading image: %s", path)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ type Manager interface {
|
|||
// Load an image idempotently into the runtime on a host
|
||||
LoadImage(string) error
|
||||
|
||||
// ImageExists takes image name and image sha checks if an it exists
|
||||
ImageExists(string, string) bool
|
||||
|
||||
// ListContainers returns a list of managed by this container runtime
|
||||
ListContainers(string) ([]string, error)
|
||||
// KillContainers removes containers based on ID
|
||||
|
|
|
|||
|
|
@ -102,6 +102,20 @@ func (r *Docker) Disable() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists
|
||||
func (r *Docker) ImageExists(name string, sha string) bool {
|
||||
// expected output looks like [SHA_ALGO:SHA]
|
||||
c := exec.Command("docker", "inspect", "--format='{{.Id}}'", name)
|
||||
rr, err := r.Runner.RunCmd(c)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if !strings.Contains(rr.Output(), sha) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// LoadImage loads an image into this runtime
|
||||
func (r *Docker) LoadImage(path string) error {
|
||||
glog.Infof("Loading image: %s", path)
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ package kubeconfig
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/clock"
|
||||
"github.com/juju/mutex"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/minikube/pkg/util/lock"
|
||||
)
|
||||
|
||||
// Settings is the minikubes settings for kubeconfig
|
||||
|
|
@ -119,8 +119,7 @@ func PopulateFromSettings(cfg *Settings, apiCfg *api.Config) error {
|
|||
// activeContext is true when minikube is the CurrentContext
|
||||
// If no CurrentContext is set, the given name will be used.
|
||||
func Update(kcs *Settings) error {
|
||||
// Add a lock around both the read, update, and write operations
|
||||
spec := mutex.Spec{Name: "kubeconfigUpdate", Clock: clock.WallClock, Delay: 10 * time.Second}
|
||||
spec := lock.PathMutexSpec(filepath.Join(kcs.filePath(), "settings.Update"))
|
||||
glog.Infof("acquiring lock: %+v", spec)
|
||||
releaser, err := mutex.Acquire(spec)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
// MinikubeHome is the name of the minikube home directory variable.
|
||||
// MinikubeHome is the name of the minikube home directory environment variable.
|
||||
const MinikubeHome = "MINIKUBE_HOME"
|
||||
|
||||
// ConfigFile is the path of the config file
|
||||
|
|
@ -46,3 +46,12 @@ func MakeMiniPath(fileName ...string) string {
|
|||
args = append(args, fileName...)
|
||||
return filepath.Join(args...)
|
||||
}
|
||||
|
||||
// MachinePath returns the Minikube machine path of a machine
|
||||
func MachinePath(machine string, miniHome ...string) string {
|
||||
miniPath := MiniPath()
|
||||
if len(miniHome) > 0 {
|
||||
miniPath = miniHome[0]
|
||||
}
|
||||
return filepath.Join(miniPath, "machines", machine)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/golang/glog"
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
|
|
@ -38,6 +39,7 @@ import (
|
|||
"golang.org/x/sync/errgroup"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
|
@ -55,7 +57,10 @@ var loadImageLock sync.Mutex
|
|||
|
||||
// CacheImagesForBootstrapper will cache images for a bootstrapper
|
||||
func CacheImagesForBootstrapper(imageRepository string, version string, clusterBootstrapper string) error {
|
||||
images := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper)
|
||||
images, err := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cached images list")
|
||||
}
|
||||
|
||||
if err := CacheImages(images, constants.ImageCacheDir); err != nil {
|
||||
return errors.Wrapf(err, "Caching images for %s", clusterBootstrapper)
|
||||
|
|
@ -92,24 +97,38 @@ func CacheImages(images []string, cacheDir string) error {
|
|||
}
|
||||
|
||||
// LoadImages loads previously cached images into the container runtime
|
||||
func LoadImages(cmd command.Runner, images []string, cacheDir string) error {
|
||||
func LoadImages(cc *config.MachineConfig, runner command.Runner, images []string, cacheDir string) error {
|
||||
glog.Infof("LoadImages start: %s", images)
|
||||
defer glog.Infof("LoadImages end")
|
||||
|
||||
var g errgroup.Group
|
||||
// Load profile cluster config from file
|
||||
cc, err := config.Load()
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
glog.Errorln("Error loading profile config: ", err)
|
||||
cr, err := cruntime.New(cruntime.Config{Type: cc.ContainerRuntime, Runner: runner})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "runtime")
|
||||
}
|
||||
|
||||
for _, image := range images {
|
||||
image := image
|
||||
g.Go(func() error {
|
||||
src := filepath.Join(cacheDir, image)
|
||||
src = sanitizeCacheDir(src)
|
||||
if err := transferAndLoadImage(cmd, cc.KubernetesConfig, src); err != nil {
|
||||
glog.Warningf("Failed to load %s: %v", src, err)
|
||||
return errors.Wrapf(err, "loading image %s", src)
|
||||
ref, err := name.ParseReference(image, name.WeakValidation)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "image name reference")
|
||||
}
|
||||
|
||||
img, err := retrieveImage(ref)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching image")
|
||||
}
|
||||
cf, err := img.ConfigName()
|
||||
hash := cf.Hex
|
||||
if err != nil {
|
||||
glog.Infof("error retrieving image manifest for %s to check if it already exists: %v", image, err)
|
||||
} else if cr.ImageExists(image, hash) {
|
||||
glog.Infof("skipping re-loading image %q because sha %q already exists ", image, hash)
|
||||
return nil
|
||||
}
|
||||
if err := transferAndLoadImage(runner, cc.KubernetesConfig, image, cacheDir); err != nil {
|
||||
glog.Warningf("Failed to load %s: %v", image, err)
|
||||
return errors.Wrapf(err, "loading image %s", image)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
@ -121,7 +140,7 @@ func LoadImages(cmd command.Runner, images []string, cacheDir string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CacheAndLoadImages caches and loads images
|
||||
// CacheAndLoadImages caches and loads images to all profiles
|
||||
func CacheAndLoadImages(images []string) error {
|
||||
if err := CacheImages(images, constants.ImageCacheDir); err != nil {
|
||||
return err
|
||||
|
|
@ -131,20 +150,38 @@ func CacheAndLoadImages(images []string) error {
|
|||
return err
|
||||
}
|
||||
defer api.Close()
|
||||
cc, err := config.Load()
|
||||
profiles, _, err := config.ListProfiles() // need to load image to all profiles
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "list profiles")
|
||||
}
|
||||
h, err := api.Load(cc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
for _, p := range profiles { // adding images to all the profiles
|
||||
pName := p.Name // capture the loop variable
|
||||
status, err := cluster.GetHostStatus(api, pName)
|
||||
if err != nil {
|
||||
glog.Warningf("skipping loading cache for profile %s", pName)
|
||||
glog.Errorf("error getting status for %s: %v", pName, err)
|
||||
continue // try next machine
|
||||
}
|
||||
if status == state.Running.String() { // the not running hosts will load on next start
|
||||
h, err := api.Load(pName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cr, err := CommandRunner(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := config.Load(pName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = LoadImages(c, cr, images, constants.ImageCacheDir)
|
||||
if err != nil {
|
||||
glog.Warningf("Failed to load cached images for profile %s. make sure the profile is running. %v", pName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runner, err := CommandRunner(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return LoadImages(runner, images, constants.ImageCacheDir)
|
||||
return err
|
||||
}
|
||||
|
||||
// # ParseReference cannot have a : in the directory path
|
||||
|
|
@ -211,7 +248,13 @@ func getWindowsVolumeNameCmd(d string) (string, error) {
|
|||
}
|
||||
|
||||
// transferAndLoadImage transfers and loads a single image from the cache
|
||||
func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, src string) error {
|
||||
func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, imgName string, cacheDir string) error {
|
||||
r, err := cruntime.New(cruntime.Config{Type: k8s.ContainerRuntime, Runner: cr})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "runtime")
|
||||
}
|
||||
src := filepath.Join(cacheDir, imgName)
|
||||
src = sanitizeCacheDir(src)
|
||||
glog.Infof("Loading image from cache: %s", src)
|
||||
filename := filepath.Base(src)
|
||||
if _, err := os.Stat(src); err != nil {
|
||||
|
|
@ -226,10 +269,6 @@ func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, src st
|
|||
return errors.Wrap(err, "transferring cached image")
|
||||
}
|
||||
|
||||
r, err := cruntime.New(cruntime.Config{Type: k8s.ContainerRuntime, Runner: cr})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "runtime")
|
||||
}
|
||||
loadImageLock.Lock()
|
||||
defer loadImageLock.Unlock()
|
||||
|
||||
|
|
@ -331,6 +370,12 @@ func CacheImage(image, dst string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { // clean up temp files
|
||||
err := os.Remove(f.Name())
|
||||
if err != nil {
|
||||
glog.Infof("Failed to clean up the temp file %s : %v", f.Name(), err)
|
||||
}
|
||||
}()
|
||||
tag, err := name.NewTag(image, name.WeakValidation)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cluster
|
||||
package machine
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
|
@ -23,8 +23,8 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// Machine contains information about a machine
|
||||
|
|
@ -60,15 +60,15 @@ func (h *Machine) IsValid() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ListMachines return all valid and invalid machines
|
||||
// List return all valid and invalid machines
|
||||
// If a machine is valid or invalid is determined by the cluster.IsValid function
|
||||
func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines []*Machine, err error) {
|
||||
func List(miniHome ...string) (validMachines []*Machine, inValidMachines []*Machine, err error) {
|
||||
pDirs, err := machineDirs(miniHome...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, n := range pDirs {
|
||||
p, err := LoadMachine(n)
|
||||
p, err := Load(n)
|
||||
if err != nil {
|
||||
glog.Infof("%s not valid: %v", n, err)
|
||||
inValidMachines = append(inValidMachines, p)
|
||||
|
|
@ -83,14 +83,14 @@ func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines
|
|||
return validMachines, inValidMachines, nil
|
||||
}
|
||||
|
||||
// LoadMachine loads a machine or throws an error if the machine could not be loadedG
|
||||
func LoadMachine(name string) (*Machine, error) {
|
||||
api, err := machine.NewAPIClient()
|
||||
// Load loads a machine or throws an error if the machine could not be loadedG
|
||||
func Load(name string) (*Machine, error) {
|
||||
api, err := NewAPIClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h, err := CheckIfHostExistsAndLoad(api, name)
|
||||
h, err := cluster.CheckIfHostExistsAndLoad(api, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -119,12 +119,3 @@ func machineDirs(miniHome ...string) (dirs []string, err error) {
|
|||
}
|
||||
return dirs, err
|
||||
}
|
||||
|
||||
// MachinePath returns the Minikube machine path of a machine
|
||||
func MachinePath(machine string, miniHome ...string) string {
|
||||
miniPath := localpath.MiniPath()
|
||||
if len(miniHome) > 0 {
|
||||
miniPath = miniHome[0]
|
||||
}
|
||||
return filepath.Join(miniPath, "machines", machine)
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cluster
|
||||
package machine
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
|
@ -51,7 +51,7 @@ func TestListMachines(t *testing.T) {
|
|||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
validMachines, inValidMachines, err := ListMachines()
|
||||
validMachines, inValidMachines, err := List()
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
|
@ -400,7 +400,7 @@ var osProblems = map[string]match{
|
|||
|
||||
// stateProblems are issues relating to local state
|
||||
var stateProblems = map[string]match{
|
||||
"MACHINE_DOES_NOT_EXST": {
|
||||
"MACHINE_DOES_NOT_EXIST": {
|
||||
Regexp: re(`Error getting state for host: machine does not exist`),
|
||||
Advice: "Run 'minikube delete' to delete the stale VM",
|
||||
Issues: []int{3864},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
|
||||
func annotateDefaultStorageClass(storage storagev1.StorageV1Interface, class *v1.StorageClass, enable bool) error {
|
||||
isDefault := strconv.FormatBool(enable)
|
||||
metav1.SetMetaDataAnnotation(&class.ObjectMeta, "storageclass.beta.kubernetes.io/is-default-class", isDefault)
|
||||
metav1.SetMetaDataAnnotation(&class.ObjectMeta, "storageclass.kubernetes.io/is-default-class", isDefault)
|
||||
_, err := storage.StorageClasses().Update(class)
|
||||
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ func configureAuth(p *BuildrootProvisioner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
config, err := config.Load()
|
||||
config, err := config.Load(p.Driver.GetMachineName())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting cluster config")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,10 @@ limitations under the License.
|
|||
package lock
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
|
@ -33,51 +31,30 @@ import (
|
|||
|
||||
// WriteFile decorates ioutil.WriteFile with a file lock and retry
|
||||
func WriteFile(filename string, data []byte, perm os.FileMode) error {
|
||||
spec := mutex.Spec{
|
||||
Name: getMutexName(filename),
|
||||
Clock: clock.WallClock,
|
||||
Delay: 13 * time.Second,
|
||||
}
|
||||
glog.Infof("attempting to write to file %q with filemode %v", filename, perm)
|
||||
|
||||
spec := PathMutexSpec(filename)
|
||||
glog.Infof("WriteFile acquiring %s: %+v", filename, spec)
|
||||
releaser, err := mutex.Acquire(spec)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error acquiring lock for %s", filename)
|
||||
return errors.Wrapf(err, "failed to acquire lock for %s: %+v", filename, spec)
|
||||
}
|
||||
|
||||
defer releaser.Release()
|
||||
|
||||
if err = ioutil.WriteFile(filename, data, perm); err != nil {
|
||||
return errors.Wrapf(err, "error writing file %s", filename)
|
||||
return errors.Wrapf(err, "writefile failed for %s", filename)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func getMutexName(filename string) string {
|
||||
// Make the mutex name the file name and its parent directory
|
||||
dir, name := filepath.Split(filename)
|
||||
|
||||
// Replace underscores and periods with dashes, the only valid punctuation for mutex name
|
||||
name = strings.ReplaceAll(name, ".", "-")
|
||||
name = strings.ReplaceAll(name, "_", "-")
|
||||
|
||||
p := strings.ReplaceAll(filepath.Base(dir), ".", "-")
|
||||
p = strings.ReplaceAll(p, "_", "-")
|
||||
mutexName := fmt.Sprintf("%s-%s", p, strings.ReplaceAll(name, ".", "-"))
|
||||
|
||||
// Check if name starts with an int and prepend a string instead
|
||||
if _, err := strconv.Atoi(mutexName[:1]); err == nil {
|
||||
mutexName = "m" + mutexName
|
||||
// PathMutexSpec returns a mutex spec for a path
|
||||
func PathMutexSpec(path string) mutex.Spec {
|
||||
s := mutex.Spec{
|
||||
Name: fmt.Sprintf("mk%x", sha1.Sum([]byte(path)))[0:40],
|
||||
Clock: clock.WallClock,
|
||||
// Poll the lock twice a second
|
||||
Delay: 500 * time.Millisecond,
|
||||
// panic after a minute instead of locking infinitely
|
||||
Timeout: 60 * time.Second,
|
||||
}
|
||||
// There's an arbitrary hard max on mutex name at 40.
|
||||
if len(mutexName) > 40 {
|
||||
mutexName = mutexName[:40]
|
||||
}
|
||||
|
||||
// Make sure name doesn't start or end with punctuation
|
||||
mutexName = strings.TrimPrefix(mutexName, "-")
|
||||
mutexName = strings.TrimSuffix(mutexName, "-")
|
||||
|
||||
return mutexName
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,13 @@ limitations under the License.
|
|||
|
||||
package lock
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
func TestGetMutexName(t *testing.T) {
|
||||
"github.com/juju/mutex"
|
||||
)
|
||||
|
||||
func TestUserMutexSpec(t *testing.T) {
|
||||
var tests = []struct {
|
||||
description string
|
||||
path string
|
||||
|
|
@ -27,41 +31,53 @@ func TestGetMutexName(t *testing.T) {
|
|||
{
|
||||
description: "standard",
|
||||
path: "/foo/bar",
|
||||
expected: "foo-bar",
|
||||
},
|
||||
{
|
||||
description: "deep directory",
|
||||
path: "/foo/bar/baz/bat",
|
||||
expected: "baz-bat",
|
||||
},
|
||||
{
|
||||
description: "underscores",
|
||||
path: "/foo_bar/baz",
|
||||
expected: "foo-bar-baz",
|
||||
},
|
||||
{
|
||||
description: "starts with number",
|
||||
path: "/foo/2bar/baz",
|
||||
expected: "m2bar-baz",
|
||||
},
|
||||
{
|
||||
description: "starts with punctuation",
|
||||
path: "/.foo/bar",
|
||||
expected: "foo-bar",
|
||||
},
|
||||
{
|
||||
description: "long filename",
|
||||
path: "/very-very-very-very-very-very-very-very-long/bar",
|
||||
expected: "very-very-very-very-very-very-very-very",
|
||||
},
|
||||
{
|
||||
description: "Windows kubeconfig",
|
||||
path: `C:\Users\admin/.kube/config`,
|
||||
},
|
||||
{
|
||||
description: "Windows json",
|
||||
path: `C:\Users\admin\.minikube\profiles\containerd-20191210T212325.7356633-8584\config.json`,
|
||||
},
|
||||
}
|
||||
|
||||
seen := map[string]string{}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
got := getMutexName(tc.path)
|
||||
if got != tc.expected {
|
||||
t.Errorf("Unexpected mutex name for path %s. got: %s, expected: %s", tc.path, got, tc.expected)
|
||||
got := PathMutexSpec(tc.path)
|
||||
if len(got.Name) != 40 {
|
||||
t.Errorf("%s is not 40 chars long", got.Name)
|
||||
}
|
||||
if seen[got.Name] != "" {
|
||||
t.Fatalf("lock name collision between %s and %s", tc.path, seen[got.Name])
|
||||
}
|
||||
m, err := mutex.Acquire(got)
|
||||
if err != nil {
|
||||
t.Errorf("acquire for spec %+v failed: %v", got, err)
|
||||
}
|
||||
m.Release()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,3 +80,22 @@ func TestConcatStrings(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateSizeInMB(t *testing.T) {
|
||||
testData := []struct {
|
||||
size string
|
||||
expectedNumber int
|
||||
}{
|
||||
{"1024kb", 1},
|
||||
{"1024KB", 1},
|
||||
{"1024mb", 1024},
|
||||
{"1024b", 0},
|
||||
}
|
||||
|
||||
for _, tt := range testData {
|
||||
number := CalculateSizeInMB(tt.size)
|
||||
if number != tt.expectedNumber {
|
||||
t.Fatalf("Expected '%d'' but got '%d'", tt.expectedNumber, number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ weight = 1
|
|||
[params]
|
||||
copyright = "The Kubernetes Authors -- "
|
||||
# The latest release of minikube
|
||||
latest_release = "1.5.2"
|
||||
latest_release = "1.6.1"
|
||||
|
||||
privacy_policy = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,3 @@ weight: 4
|
|||
description: >
|
||||
Concepts that users and contributors should be aware of.
|
||||
---
|
||||
|
||||
{{% pageinfo %}}
|
||||
This is a placeholder page that shows you how to use this template site.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
For many projects, users may not need much information beyond the information in the [Overview](/docs/overview/), so this section is **optional**. However if there are areas where your users will need a more detailed understanding of a given term or feature in order to do anything useful with your project (or to not make mistakes when using it) put that information in this section. For example, you may want to add some conceptual pages if you have a large project with many components and a complex architecture.
|
||||
|
||||
Remember to focus on what the user needs to know, not just what you think is interesting about your project! If they don’t need to understand your original design decisions to use or contribute to the project, don’t put them in, or include your design docs in your repo and link to them. Similarly, most users will probably need to know more about how features work when in use rather than how they are implemented. Consider a separate architecture page for more detailed implementation and system design information that potential project contributors can consult.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Proper installation of KVM and libvirt is highly specific to each Linux distribu
|
|||
* [Debian](https://wiki.debian.org/KVM#Installation)
|
||||
* [Fedora](https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-virtualization/)
|
||||
* [Gentoo](https://wiki.gentoo.org/wiki/QEMU)
|
||||
* [OpenSUSE](https://doc.opensuse.org/documentation/leap/virtualization/html/book.virt/cha.vt.installation.html)
|
||||
* [OpenSUSE](https://doc.opensuse.org/documentation/leap/virtualization/html/book.virt/cha-vt-installation.html)
|
||||
* [RedHat](https://access.redhat.com/articles/1344173#Q_how-install-virtualization-packages)
|
||||
* [Ubuntu](https://help.ubuntu.com/community/KVM/Installation)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: "Audit Policy"
|
||||
linkTitle: "Audit Policy"
|
||||
weight: 1
|
||||
date: 2019-11-19
|
||||
description: >
|
||||
Enabling audit policy for minikube
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
[Auditing](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/) is not enabled in minikube by default.
|
||||
This tutorial shows how to provide an [Audit Policy](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-policy) file to the minikube API server on startup.
|
||||
|
||||
## Tutorial
|
||||
|
||||
```shell
|
||||
minikube stop
|
||||
|
||||
mkdir -p ~/.minikube/files/etc/ssl/certs
|
||||
|
||||
cat <<EOF > ~/.minikube/files/etc/ssl/certs/audit-policy.yaml
|
||||
# Log all requests at the Metadata level.
|
||||
apiVersion: audit.k8s.io/v1
|
||||
kind: Policy
|
||||
rules:
|
||||
- level: Metadata
|
||||
EOF
|
||||
|
||||
minikube start \
|
||||
--extra-config=apiserver.audit-policy-file=/etc/ssl/certs/audit-policy.yaml \
|
||||
--extra-config=apiserver.audit-log-path=-
|
||||
|
||||
kubectl logs kube-apiserver-minikube -n kube-system | grep audit.k8s.io/v1
|
||||
```
|
||||
|
||||
The [Audit Policy](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-policy) used in this tutorial is very minimal and quite verbose. As a next step you might want to finetune the `audit-policy.yaml` file. To get the changes applied you need to stop and start minikube. Restarting minikube triggers the [file sync mechanism](https://minikube.sigs.k8s.io/docs/tasks/sync/) that copies the yaml file onto the minikube node and causes the API server to read the changed policy file.
|
||||
|
||||
Note: Currently there is no dedicated directory to store the `audit-policy.yaml` file in `~/.minikube/`. Using the `~/.minikube/files/etc/ssl/certs` directory is a workaround! This workaround works like this: By putting the file into a sub-directory of `~/.minikube/files/`, the [file sync mechanism](https://minikube.sigs.k8s.io/docs/tasks/sync/) gets triggered and copies the `audit-policy.yaml` file from the host onto the minikube node. When the API server container gets started by `kubeadm` I'll mount the `/etc/ssl/certs` directory from the minikube node into the container. This is the reason why the `audit-policy.yaml` file has to be stored in the ssl certs directory: It's one of the directories that get mounted from the minikube node into the container.
|
||||
|
|
@ -67,7 +67,11 @@ func TestDownloadOnly(t *testing.T) {
|
|||
t.Errorf("%s failed: %v", args, err)
|
||||
}
|
||||
|
||||
imgs := images.CachedImages("", v)
|
||||
imgs, err := images.Kubeadm("", v)
|
||||
if err != nil {
|
||||
t.Errorf("kubeadm images: %v", v)
|
||||
}
|
||||
|
||||
for _, img := range imgs {
|
||||
img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2
|
||||
fp := filepath.Join(localpath.MiniPath(), "cache", "images", img)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func TestDockerFlags(t *testing.T) {
|
|||
defer CleanupWithLogs(t, profile, cancel)
|
||||
|
||||
// Use the most verbose logging for the simplest test. If it fails, something is very wrong.
|
||||
args := append([]string{"start", "-p", profile, "--wait=false", "--docker-env=FOO=BAR", "--docker-env=BAZ=BAT", "--docker-opt=debug", "--docker-opt=icc=true", "--alsologtostderr", "-v=5"}, StartArgs()...)
|
||||
args := append([]string{"start", "-p", profile, "--cache-images=false", "--wait=false", "--docker-env=FOO=BAR", "--docker-env=BAZ=BAT", "--docker-opt=debug", "--docker-opt=icc=true", "--alsologtostderr", "-v=5"}, StartArgs()...)
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,13 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
|
||||
"github.com/elazarl/goproxy"
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/otiai10/copy"
|
||||
"github.com/phayes/freeport"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/build/kubernetes/api"
|
||||
|
|
@ -59,6 +64,7 @@ func TestFunctional(t *testing.T) {
|
|||
name string
|
||||
validator validateFunc
|
||||
}{
|
||||
{"CopySyncFile", setupFileSync}, // Set file for the file sync test case
|
||||
{"StartWithProxy", validateStartWithProxy}, // Set everything else up for success
|
||||
{"KubeContext", validateKubeContext}, // Racy: must come immediately after "minikube start"
|
||||
{"KubectlGetPods", validateKubectlGetPods}, // Make sure apiserver is up
|
||||
|
|
@ -96,6 +102,8 @@ func TestFunctional(t *testing.T) {
|
|||
{"TunnelCmd", validateTunnelCmd},
|
||||
{"SSHCmd", validateSSHCmd},
|
||||
{"MySQL", validateMySQL},
|
||||
{"FileSync", validateFileSync},
|
||||
{"UpdateContextCmd", validateUpdateContextCmd},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
|
|
@ -301,17 +309,51 @@ func validateDNS(ctx context.Context, t *testing.T, profile string) {
|
|||
}
|
||||
}
|
||||
|
||||
// validateCacheCmd asserts basic "ssh" command functionality
|
||||
// validateCacheCmd tests functionality of cache command (cache add, delete, list)
|
||||
func validateCacheCmd(ctx context.Context, t *testing.T, profile string) {
|
||||
if NoneDriver() {
|
||||
t.Skipf("skipping: cache unsupported by none")
|
||||
}
|
||||
for _, img := range []string{"busybox", "busybox:1.28.4-glibc", "mysql:5.6", "gcr.io/hello-minikube-zero-install/hello-node"} {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "cache", "add", img))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
}
|
||||
t.Run("cache", func(t *testing.T) {
|
||||
t.Run("add", func(t *testing.T) {
|
||||
for _, img := range []string{"busybox", "busybox:1.28.4-glibc", "k8s.gcr.io/pause:latest"} {
|
||||
_, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "cache", "add", img))
|
||||
if err != nil {
|
||||
t.Errorf("Failed to cache image %q", img)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("delete", func(t *testing.T) {
|
||||
_, err := Run(t, exec.CommandContext(ctx, Target(), "cache", "delete", "busybox:1.28.4-glibc"))
|
||||
if err != nil {
|
||||
t.Errorf("failed to delete image busybox:1.28.4-glibc from cache: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("list", func(t *testing.T) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "cache", "list"))
|
||||
if err != nil {
|
||||
t.Errorf("cache list failed: %v", err)
|
||||
}
|
||||
if !strings.Contains(rr.Output(), "k8s.gcr.io/pause") {
|
||||
t.Errorf("cache list did not include k8s.gcr.io/pause")
|
||||
}
|
||||
if strings.Contains(rr.Output(), "busybox:1.28.4-glibc") {
|
||||
t.Errorf("cache list should not include busybox:1.28.4-glibc")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("verify cache inside node", func(t *testing.T) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "sudo", "crictl", "images"))
|
||||
if err != nil {
|
||||
t.Errorf("failed to get docker images through ssh %v", err)
|
||||
}
|
||||
if !strings.Contains(rr.Output(), "1.28.4-glibc") {
|
||||
t.Errorf("expected '1.28.4-glibc' to be in the output: %s", rr.Output())
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// validateConfigCmd asserts basic "config" command functionality
|
||||
|
|
@ -573,6 +615,50 @@ func validateMySQL(ctx context.Context, t *testing.T, profile string) {
|
|||
}
|
||||
}
|
||||
|
||||
// Copy extra file into minikube home folder for file sync test
|
||||
func setupFileSync(ctx context.Context, t *testing.T, profile string) {
|
||||
// 1. copy random file to MINIKUBE_HOME/files/etc
|
||||
f := filepath.Join(localpath.MiniPath(), "/files/etc/sync.test")
|
||||
err := copy.Copy("./testdata/sync.test", f)
|
||||
if err != nil {
|
||||
t.Fatalf("copy: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// validateFileSync to check existence of the test file
|
||||
func validateFileSync(ctx context.Context, t *testing.T, profile string) {
|
||||
if NoneDriver() {
|
||||
t.Skipf("skipping: ssh unsupported by none")
|
||||
}
|
||||
// check file existence
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "cat /etc/sync.test"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile("./testdata/sync.test")
|
||||
if err != nil {
|
||||
t.Errorf("test file not found: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(string(expected), rr.Stdout.String()); diff != "" {
|
||||
t.Errorf("/etc/sync.test content mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// validateUpdateContextCmd asserts basic "update-context" command functionality
|
||||
func validateUpdateContextCmd(ctx context.Context, t *testing.T, profile string) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "update-context", "--alsologtostderr", "-v=2"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
|
||||
want := []byte("IP was already correctly configured")
|
||||
if !bytes.Contains(rr.Stdout.Bytes(), want) {
|
||||
t.Errorf("update-context: got=%q, want=*%q*", rr.Stdout.Bytes(), want)
|
||||
}
|
||||
}
|
||||
|
||||
// startHTTPProxy runs a local http proxy and sets the env vars for it.
|
||||
func startHTTPProxy(t *testing.T) (*http.Server, error) {
|
||||
port, err := freeport.GetFreePort()
|
||||
|
|
|
|||
|
|
@ -20,15 +20,19 @@ package integration
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper/images"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
|
|
@ -37,12 +41,11 @@ func TestStartStop(t *testing.T) {
|
|||
|
||||
t.Run("group", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
name string
|
||||
version string
|
||||
args []string
|
||||
}{
|
||||
{"docker", []string{
|
||||
"--cache-images=false",
|
||||
fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
|
||||
{"old-docker", constants.OldestKubernetesVersion, []string{
|
||||
// default is the network created by libvirt, if we change the name minikube won't boot
|
||||
// because the given network doesn't exist
|
||||
"--kvm-network=default",
|
||||
|
|
@ -51,21 +54,20 @@ func TestStartStop(t *testing.T) {
|
|||
"--keep-context=false",
|
||||
"--container-runtime=docker",
|
||||
}},
|
||||
{"cni", []string{
|
||||
{"newest-cni", constants.NewestKubernetesVersion, []string{
|
||||
"--feature-gates",
|
||||
"ServerSideApply=true",
|
||||
"--network-plugin=cni",
|
||||
"--extra-config=kubelet.network-plugin=cni",
|
||||
"--extra-config=kubeadm.pod-network-cidr=192.168.111.111/16",
|
||||
fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
|
||||
}},
|
||||
{"containerd", []string{
|
||||
{"containerd", constants.DefaultKubernetesVersion, []string{
|
||||
"--container-runtime=containerd",
|
||||
"--docker-opt",
|
||||
"containerd=/var/run/containerd/containerd.sock",
|
||||
"--apiserver-port=8444",
|
||||
}},
|
||||
{"crio", []string{
|
||||
{"crio", "v1.15.0", []string{
|
||||
"--container-runtime=crio",
|
||||
"--disable-driver-mounts",
|
||||
"--extra-config=kubeadm.ignore-preflight-errors=SystemVerification",
|
||||
|
|
@ -88,6 +90,7 @@ func TestStartStop(t *testing.T) {
|
|||
|
||||
startArgs := append([]string{"start", "-p", profile, "--alsologtostderr", "-v=3", "--wait=true"}, tc.args...)
|
||||
startArgs = append(startArgs, StartArgs()...)
|
||||
startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", tc.version))
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), startArgs...))
|
||||
if err != nil {
|
||||
// Fatal so that we may collect logs before stop/delete steps
|
||||
|
|
@ -144,6 +147,40 @@ func TestStartStop(t *testing.T) {
|
|||
t.Fatalf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
|
||||
// Make sure that kubeadm did not need to pull in additional images
|
||||
if !NoneDriver() {
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "sudo crictl images -o json"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
jv := map[string][]struct {
|
||||
Tags []string `json:"repoTags"`
|
||||
}{}
|
||||
err = json.Unmarshal(rr.Stdout.Bytes(), &jv)
|
||||
if err != nil {
|
||||
t.Errorf("images unmarshal: %v", err)
|
||||
}
|
||||
gotImages := []string{}
|
||||
for _, img := range jv["images"] {
|
||||
for _, i := range img.Tags {
|
||||
// Ignore non-Kubernetes images
|
||||
if !strings.Contains(i, "ingress") && !strings.Contains(i, "busybox") {
|
||||
// Remove docker.io for naming consistency between container runtimes
|
||||
gotImages = append(gotImages, strings.TrimPrefix(i, "docker.io/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
want, err := images.Kubeadm("", tc.version)
|
||||
if err != nil {
|
||||
t.Errorf("kubeadm images: %v", tc.version)
|
||||
}
|
||||
sort.Strings(want)
|
||||
sort.Strings(gotImages)
|
||||
if diff := cmp.Diff(want, gotImages); diff != "" {
|
||||
t.Errorf("%s images mismatch (-want +got):\n%s", tc.version, diff)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(tc.name, "cni") {
|
||||
t.Logf("WARNING: cni mode requires additional setup before pods can schedule :(")
|
||||
} else if _, err := PodWait(ctx, t, profile, "default", "integration-test=busybox", 2*time.Minute); err != nil {
|
||||
|
|
@ -155,7 +192,7 @@ func TestStartStop(t *testing.T) {
|
|||
t.Errorf("status = %q; want = %q", got, state.Running)
|
||||
}
|
||||
|
||||
if !*cleanup {
|
||||
if *cleanup {
|
||||
// Normally handled by cleanuprofile, but not fatal there
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile))
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Test file for checking file sync process
|
||||
|
|
@ -18,6 +18,7 @@ package integration
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -28,6 +29,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
|
||||
|
|
@ -66,13 +68,13 @@ func TestVersionUpgrade(t *testing.T) {
|
|||
|
||||
args := append([]string{"start", "-p", profile, fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion), "--alsologtostderr", "-v=1"}, StartArgs()...)
|
||||
rr := &RunResult{}
|
||||
releaseStart := func() error {
|
||||
r := func() error {
|
||||
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), args...))
|
||||
return err
|
||||
}
|
||||
|
||||
// Retry to allow flakiness for the previous release
|
||||
if err := retry.Expo(releaseStart, 1*time.Second, 30*time.Minute, 3); err != nil {
|
||||
if err := retry.Expo(r, 1*time.Second, 30*time.Minute, 3); err != nil {
|
||||
t.Fatalf("release start failed: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -96,4 +98,34 @@ func TestVersionUpgrade(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
|
||||
s, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "version", "--output=json"))
|
||||
if err != nil {
|
||||
t.Fatalf("error running kubectl: %v", err)
|
||||
}
|
||||
cv := struct {
|
||||
ServerVersion struct {
|
||||
GitVersion string `json:"gitVersion"`
|
||||
} `json:"serverVersion"`
|
||||
}{}
|
||||
err = json.Unmarshal(s.Stdout.Bytes(), &cv)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error traversing json output: %v", err)
|
||||
}
|
||||
|
||||
if cv.ServerVersion.GitVersion != constants.NewestKubernetesVersion {
|
||||
t.Fatalf("expected server version %s is not the same with latest version %s", cv.ServerVersion.GitVersion, constants.NewestKubernetesVersion)
|
||||
}
|
||||
|
||||
args = append([]string{"start", "-p", profile, fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion), "--alsologtostderr", "-v=1"}, StartArgs()...)
|
||||
rr = &RunResult{}
|
||||
r = func() error {
|
||||
rr, err = Run(t, exec.CommandContext(ctx, tf.Name(), args...))
|
||||
return err
|
||||
}
|
||||
|
||||
if err := retry.Expo(r, 1*time.Second, 30*time.Minute, 3); err == nil {
|
||||
t.Fatalf("downgrading kubernetes should not be allowed: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue