commit
be196bfe9d
|
@ -64,11 +64,6 @@ jobs:
|
|||
echo workspace $GITHUB_WORKSPACE
|
||||
echo "end of debug stuff"
|
||||
echo $(which jq)
|
||||
# iso needs golang 1.11.3
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.11.13'
|
||||
stable: true
|
||||
- name: Build ISO
|
||||
run: |
|
||||
whoami
|
||||
|
@ -146,4 +141,4 @@ jobs:
|
|||
if [ "$numFail" -gt 0 ];then echo "*** $numFail Failed ***";exit 2;fi
|
||||
if [ "$numPass" -eq 0 ];then echo "*** 0 Passed! ***";exit 2;fi
|
||||
if [ "$numPass" -lt 32 ];then echo "*** Failed to pass at least 32 ! ***";exit 2;fi
|
||||
if [ "$numPass" -eq 0 ];then echo "*** Passed! ***";exit 0;fi
|
||||
if [ "$numPass" -eq 0 ];then echo "*** Passed! ***";exit 0;fi
|
||||
|
|
|
@ -412,7 +412,7 @@ jobs:
|
|||
echo "---------------- ${numFail} Failures :( ----------------------------"
|
||||
echo $failedTests
|
||||
echo "-------------------------------------------------------"
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numPass -eq 0){ exit 2 }
|
||||
If ($numPass -lt 33){ exit 2 }
|
||||
If ($numFail -eq 0){ exit 0 }
|
||||
|
@ -429,7 +429,7 @@ jobs:
|
|||
shell: powershell
|
||||
run: |
|
||||
echo $env:computerName
|
||||
ls
|
||||
ls
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
cd minikube_binaries
|
||||
ls
|
||||
|
@ -464,14 +464,14 @@ jobs:
|
|||
$docker_running = $?
|
||||
}
|
||||
Write-Output "Docker is running"
|
||||
docker system prune -f
|
||||
docker system prune -f
|
||||
- name: Info
|
||||
continue-on-error: true
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
cd minikube_binaries
|
||||
ls
|
||||
ls
|
||||
echo $env:computername
|
||||
Get-WmiObject -class Win32_ComputerSystem
|
||||
- uses: actions/setup-go@v2
|
||||
|
@ -483,7 +483,7 @@ jobs:
|
|||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/medyagh/gopogh/releases/download/v0.2.4/gopogh.exe", "C:\ProgramData\chocolatey\bin\gopogh.exe")
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/medyagh/gopogh/releases/download/v0.2.4/gopogh.exe", "C:\ProgramData\chocolatey\bin\gopogh.exe")
|
||||
choco install -y kubernetes-cli
|
||||
choco install -y jq
|
||||
choco install -y caffeine
|
||||
|
@ -549,7 +549,7 @@ jobs:
|
|||
echo "---------------- ${numFail} Failures :( ----------------------------"
|
||||
echo $failedTests
|
||||
echo "-------------------------------------------------------"
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numPass -eq 0){ exit 2 }
|
||||
If ($numPass -lt 33){ exit 2 }
|
||||
If ($numFail -eq 0){ exit 0 }
|
||||
|
@ -775,11 +775,11 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw -k
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw -k
|
||||
- name: Download Binaries
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
|
@ -966,7 +966,7 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
|
@ -1150,7 +1150,7 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
|
@ -1247,4 +1247,4 @@ jobs:
|
|||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: all_reports
|
||||
path: all_reports
|
||||
path: all_reports
|
|
@ -410,7 +410,7 @@ jobs:
|
|||
echo "---------------- ${numFail} Failures :( ----------------------------"
|
||||
echo $failedTests
|
||||
echo "-------------------------------------------------------"
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numPass -eq 0){ exit 2 }
|
||||
If ($numPass -lt 33){ exit 2 }
|
||||
If ($numFail -eq 0){ exit 0 }
|
||||
|
@ -427,7 +427,7 @@ jobs:
|
|||
shell: powershell
|
||||
run: |
|
||||
echo $env:computerName
|
||||
ls
|
||||
ls
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
cd minikube_binaries
|
||||
ls
|
||||
|
@ -462,14 +462,14 @@ jobs:
|
|||
$docker_running = $?
|
||||
}
|
||||
Write-Output "Docker is running"
|
||||
docker system prune -f
|
||||
docker system prune -f
|
||||
- name: Info
|
||||
continue-on-error: true
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
cd minikube_binaries
|
||||
ls
|
||||
ls
|
||||
echo $env:computername
|
||||
Get-WmiObject -class Win32_ComputerSystem
|
||||
- uses: actions/setup-go@v2
|
||||
|
@ -481,7 +481,7 @@ jobs:
|
|||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/medyagh/gopogh/releases/download/v0.2.4/gopogh.exe", "C:\ProgramData\chocolatey\bin\gopogh.exe")
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/medyagh/gopogh/releases/download/v0.2.4/gopogh.exe", "C:\ProgramData\chocolatey\bin\gopogh.exe")
|
||||
choco install -y kubernetes-cli
|
||||
choco install -y jq
|
||||
choco install -y caffeine
|
||||
|
@ -547,7 +547,7 @@ jobs:
|
|||
echo "---------------- ${numFail} Failures :( ----------------------------"
|
||||
echo $failedTests
|
||||
echo "-------------------------------------------------------"
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numFail -gt 0){ exit 2 }
|
||||
If ($numPass -eq 0){ exit 2 }
|
||||
If ($numPass -lt 33){ exit 2 }
|
||||
If ($numFail -eq 0){ exit 0 }
|
||||
|
@ -773,11 +773,11 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw -k
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw -k
|
||||
- name: Download Binaries
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
|
@ -964,7 +964,7 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
|
@ -1148,7 +1148,7 @@ jobs:
|
|||
run: |
|
||||
hostname
|
||||
VBoxManage --version
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
sysctl hw.physicalcpu hw.logicalcpu
|
||||
- name: Disable firewall
|
||||
run: |
|
||||
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||
|
@ -1245,4 +1245,4 @@ jobs:
|
|||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: all_reports
|
||||
path: all_reports
|
||||
path: all_reports
|
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -1,5 +1,31 @@
|
|||
# Release Notes
|
||||
|
||||
## Version 1.13.1 - 2020-09-18
|
||||
* Update Default Kubernetes Version to v1.19.2 [#9265](https://github.com/kubernetes/minikube/pull/9265)
|
||||
* fix mounting for docker driver in windows [#9263](https://github.com/kubernetes/minikube/pull/9263)
|
||||
* CSI Hostpath Driver & VolumeSnapshots addons [#8461](https://github.com/kubernetes/minikube/pull/8461)
|
||||
* docker/podman drivers: Make sure CFS_BANDWIDTH is available for --cpus [#9255](https://github.com/kubernetes/minikube/pull/9255)
|
||||
* Fix ForwardedPort for podman version 2.0.1 and up [#9237](https://github.com/kubernetes/minikube/pull/9237)
|
||||
* Avoid setting time for memory assets [#9256](https://github.com/kubernetes/minikube/pull/9256)
|
||||
* point to newest gcp-auth-webhook version [#9199](https://github.com/kubernetes/minikube/pull/9199)
|
||||
* Set preload=false if not using overlay2 as docker storage driver [#8831](https://github.com/kubernetes/minikube/pull/8831)
|
||||
* Upgrade crio to 1.17.3 [#8922](https://github.com/kubernetes/minikube/pull/8922)
|
||||
* Add Docker Desktop instructions if memory is greater than minimum but less than recommended [#9181](https://github.com/kubernetes/minikube/pull/9181)
|
||||
* Update minimum memory constants to use MiB instead of MB [#9180](https://github.com/kubernetes/minikube/pull/9180)
|
||||
|
||||
Thank you to our contributors for this release!
|
||||
- Anders F Björklund
|
||||
- Dean Coakley
|
||||
- Julien Breux
|
||||
- Li Zhijian
|
||||
- Medya Ghazizadeh
|
||||
- Priya Wadhwa
|
||||
- Sharif Elgamal
|
||||
- Thomas Strömberg
|
||||
- Zadjad Rezai
|
||||
- jjanik
|
||||
|
||||
|
||||
## Version 1.13.0 - 2020-09-03
|
||||
|
||||
## Features
|
||||
|
|
22
Makefile
22
Makefile
|
@ -15,7 +15,7 @@
|
|||
# Bump these on release - and please check ISO_VERSION for correctness.
|
||||
VERSION_MAJOR ?= 1
|
||||
VERSION_MINOR ?= 13
|
||||
VERSION_BUILD ?= 0
|
||||
VERSION_BUILD ?= 1
|
||||
RAW_VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD)
|
||||
VERSION ?= v$(RAW_VERSION)
|
||||
|
||||
|
@ -23,7 +23,7 @@ KUBERNETES_VERSION ?= $(shell egrep "DefaultKubernetesVersion =" pkg/minikube/co
|
|||
KIC_VERSION ?= $(shell egrep "Version =" pkg/drivers/kic/types.go | cut -d \" -f2)
|
||||
|
||||
# Default to .0 for higher cache hit rates, as build increments typically don't require new ISO versions
|
||||
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).0
|
||||
ISO_VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).1
|
||||
# Dashes are valid in semver, but not Linux packaging. Use ~ to delimit alpha/beta
|
||||
DEB_VERSION ?= $(subst -,~,$(RAW_VERSION))
|
||||
RPM_VERSION ?= $(DEB_VERSION)
|
||||
|
@ -305,9 +305,15 @@ html_report: ## Generate HTML report out of the last ran integration test logs.
|
|||
@go tool test2json -t < "./out/testout_$(COMMIT_SHORT).txt" > "./out/testout_$(COMMIT_SHORT).json"
|
||||
@gopogh -in "./out/testout_$(COMMIT_SHORT).json" -out ./out/testout_$(COMMIT_SHORT).html -name "$(shell git rev-parse --abbrev-ref HEAD)" -pr "" -repo github.com/kubernetes/minikube/ -details "${COMMIT_SHORT}"
|
||||
@echo "-------------------------- Open HTML Report in Browser: ---------------------------"
|
||||
ifeq ($(GOOS),windows)
|
||||
@echo start $(CURDIR)/out/testout_$(COMMIT_SHORT).html
|
||||
@echo "-----------------------------------------------------------------------------------"
|
||||
@start $(CURDIR)/out/testout_$(COMMIT_SHORT).html || true
|
||||
else
|
||||
@echo open $(CURDIR)/out/testout_$(COMMIT_SHORT).html
|
||||
@echo "-----------------------------------------------------------------------------------"
|
||||
@open $(CURDIR)/out/testout_$(COMMIT_SHORT).html || true
|
||||
endif
|
||||
|
||||
.PHONY: test
|
||||
test: pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go ## Trigger minikube test
|
||||
|
@ -331,7 +337,7 @@ pkg/minikube/assets/assets.go: $(shell find "deploy/addons" -type f)
|
|||
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
|
||||
endif
|
||||
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
|
||||
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/go-bindata/go-bindata/...
|
||||
$(if $(quiet),@echo " GEN $@")
|
||||
$(Q)PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
|
||||
$(Q)-gofmt -s -w $@
|
||||
|
@ -344,7 +350,7 @@ pkg/minikube/translate/translations.go: $(shell find "translations/" -type f)
|
|||
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
|
||||
endif
|
||||
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
|
||||
@which go-bindata >/dev/null 2>&1 || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/go-bindata/go-bindata/...
|
||||
$(if $(quiet),@echo " GEN $@")
|
||||
$(Q)PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
|
||||
$(Q)-gofmt -s -w $@
|
||||
|
@ -579,7 +585,7 @@ storage-provisioner-image: out/storage-provisioner-$(GOARCH) ## Build storage-pr
|
|||
.PHONY: kic-base-image
|
||||
kic-base-image: ## builds the base image used for kic.
|
||||
docker rmi -f $(KIC_BASE_IMAGE_GCR)-snapshot || true
|
||||
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION)-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(KIC_BASE_IMAGE_GCR) --target base ./deploy/kicbase
|
||||
docker build -f ./deploy/kicbase/Dockerfile -t local/kicbase:$(KIC_VERSION)-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) --cache-from $(KIC_BASE_IMAGE_GCR) ./deploy/kicbase
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GCR)-snapshot
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_GCR)
|
||||
docker tag local/kicbase:$(KIC_VERSION)-snapshot $(KIC_BASE_IMAGE_HUB)
|
||||
|
@ -747,9 +753,9 @@ site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo ## Serv
|
|||
out/mkcmp:
|
||||
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: out/performance-bot
|
||||
out/performance-bot:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/pr-bot/bot.go
|
||||
|
||||
.PHONY: compare
|
||||
compare: out/mkcmp out/minikube
|
||||
|
|
|
@ -28,8 +28,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/reason"
|
||||
)
|
||||
|
||||
const longDescription = `
|
||||
Outputs minikube shell completion for the given shell (bash, zsh or fish)
|
||||
const longDescription = `Outputs minikube shell completion for the given shell (bash, zsh or fish)
|
||||
|
||||
This depends on the bash-completion binary. Example installation instructions:
|
||||
OS X:
|
||||
|
|
|
@ -32,8 +32,8 @@ import (
|
|||
|
||||
var addonsConfigureCmd = &cobra.Command{
|
||||
Use: "configure ADDON_NAME",
|
||||
Short: "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list ",
|
||||
Long: "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list ",
|
||||
Short: "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list",
|
||||
Long: "Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 1 {
|
||||
exit.Message(reason.Usage, "usage: minikube addons configure ADDON_NAME")
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil/kverify"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
|
@ -31,6 +32,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/reason"
|
||||
"k8s.io/minikube/pkg/minikube/style"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/golang/glog"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -54,96 +56,114 @@ var profileListCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
var printProfilesTable = func() {
|
||||
var validData [][]string
|
||||
func printProfilesTable() {
|
||||
validProfiles, invalidProfiles, err := config.ListProfiles()
|
||||
|
||||
if err != nil {
|
||||
glog.Warningf("error loading profiles: %v", err)
|
||||
}
|
||||
|
||||
if len(validProfiles) == 0 {
|
||||
exit.Message(reason.Usage, "No minikube profile was found. You can create one using `minikube start`.")
|
||||
}
|
||||
|
||||
updateProfilesStatus(validProfiles)
|
||||
renderProfilesTable(profilesToTableData(validProfiles))
|
||||
warnInvalidProfiles(invalidProfiles)
|
||||
}
|
||||
|
||||
func updateProfilesStatus(profiles []*config.Profile) {
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
glog.Errorf("failed to get machine api client %v", err)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
for _, p := range profiles {
|
||||
p.Status = profileStatus(p, api)
|
||||
}
|
||||
}
|
||||
|
||||
func profileStatus(p *config.Profile, api libmachine.API) string {
|
||||
cp, err := config.PrimaryControlPlane(p.Config)
|
||||
if err != nil {
|
||||
exit.Error(reason.GuestCpConfig, "error getting primary control plane", err)
|
||||
}
|
||||
|
||||
host, err := machine.LoadHost(api, driver.MachineName(*p.Config, cp))
|
||||
if err != nil {
|
||||
glog.Warningf("error loading profiles: %v", err)
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
cr, err := machine.CommandRunner(host)
|
||||
if err != nil {
|
||||
glog.Warningf("error loading profiles: %v", err)
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
hostname, _, port, err := driver.ControlPlaneEndpoint(p.Config, &cp, host.DriverName)
|
||||
if err != nil {
|
||||
glog.Warningf("error loading profiles: %v", err)
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
status, err := kverify.APIServerStatus(cr, hostname, port)
|
||||
if err != nil {
|
||||
glog.Warningf("error getting apiserver status for %s: %v", p.Name, err)
|
||||
return "Unknown"
|
||||
}
|
||||
return status.String()
|
||||
}
|
||||
|
||||
func renderProfilesTable(ps [][]string) {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Profile", "VM Driver", "Runtime", "IP", "Port", "Version", "Status"})
|
||||
table.SetAutoFormatHeaders(false)
|
||||
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
|
||||
table.SetCenterSeparator("|")
|
||||
validProfiles, invalidProfiles, err := config.ListProfiles()
|
||||
table.AppendBulk(ps)
|
||||
table.Render()
|
||||
}
|
||||
|
||||
if len(validProfiles) == 0 || err != nil {
|
||||
exit.Message(reason.Usage, "No minikube profile was found. You can create one using `minikube start`.")
|
||||
}
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
glog.Errorf("failed to get machine api client %v", err)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
for _, p := range validProfiles {
|
||||
func profilesToTableData(profiles []*config.Profile) [][]string {
|
||||
var data [][]string
|
||||
for _, p := range profiles {
|
||||
cp, err := config.PrimaryControlPlane(p.Config)
|
||||
if err != nil {
|
||||
exit.Error(reason.GuestCpConfig, "error getting primary control plane", err)
|
||||
}
|
||||
p.Status, err = machine.Status(api, driver.MachineName(*p.Config, cp))
|
||||
if err != nil {
|
||||
glog.Warningf("error getting host status for %s: %v", p.Name, err)
|
||||
}
|
||||
validData = append(validData, []string{p.Name, p.Config.Driver, p.Config.KubernetesConfig.ContainerRuntime, cp.IP, strconv.Itoa(cp.Port), p.Config.KubernetesConfig.KubernetesVersion, p.Status})
|
||||
|
||||
data = append(data, []string{p.Name, p.Config.Driver, p.Config.KubernetesConfig.ContainerRuntime, cp.IP, strconv.Itoa(cp.Port), p.Config.KubernetesConfig.KubernetesVersion, p.Status})
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func warnInvalidProfiles(invalidProfiles []*config.Profile) {
|
||||
if invalidProfiles == nil {
|
||||
return
|
||||
}
|
||||
|
||||
table.AppendBulk(validData)
|
||||
table.Render()
|
||||
|
||||
if invalidProfiles != nil {
|
||||
out.WarningT("Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)})
|
||||
for _, p := range invalidProfiles {
|
||||
out.ErrT(style.Empty, "\t "+p.Name)
|
||||
}
|
||||
out.ErrT(style.Tip, "You can delete them using the following command(s): ")
|
||||
for _, p := range invalidProfiles {
|
||||
out.Err(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name))
|
||||
}
|
||||
|
||||
out.WarningT("Found {{.number}} invalid profile(s) ! ", out.V{"number": len(invalidProfiles)})
|
||||
for _, p := range invalidProfiles {
|
||||
out.ErrT(style.Empty, "\t "+p.Name)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
glog.Warningf("error loading profiles: %v", err)
|
||||
out.ErrT(style.Tip, "You can delete them using the following command(s): ")
|
||||
for _, p := range invalidProfiles {
|
||||
out.Err(fmt.Sprintf("\t $ minikube delete -p %s \n", p.Name))
|
||||
}
|
||||
}
|
||||
|
||||
var printProfilesJSON = func() {
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
glog.Errorf("failed to get machine api client %v", err)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
func printProfilesJSON() {
|
||||
validProfiles, invalidProfiles, err := config.ListProfiles()
|
||||
for _, v := range validProfiles {
|
||||
cp, err := config.PrimaryControlPlane(v.Config)
|
||||
if err != nil {
|
||||
exit.Error(reason.GuestCpConfig, "error getting primary control plane", err)
|
||||
}
|
||||
status, err := machine.Status(api, driver.MachineName(*v.Config, cp))
|
||||
if err != nil {
|
||||
glog.Warningf("error getting host status for %s: %v", v.Name, err)
|
||||
}
|
||||
v.Status = status
|
||||
}
|
||||
|
||||
var valid []*config.Profile
|
||||
var invalid []*config.Profile
|
||||
|
||||
if validProfiles != nil {
|
||||
valid = validProfiles
|
||||
} else {
|
||||
valid = []*config.Profile{}
|
||||
}
|
||||
|
||||
if invalidProfiles != nil {
|
||||
invalid = invalidProfiles
|
||||
} else {
|
||||
invalid = []*config.Profile{}
|
||||
}
|
||||
|
||||
body := map[string]interface{}{}
|
||||
updateProfilesStatus(validProfiles)
|
||||
|
||||
var body = map[string]interface{}{}
|
||||
if err == nil || config.IsNotExist(err) {
|
||||
body["valid"] = valid
|
||||
body["invalid"] = invalid
|
||||
body["valid"] = profilesOrDefault(validProfiles)
|
||||
body["invalid"] = profilesOrDefault(invalidProfiles)
|
||||
jsonString, _ := json.Marshal(body)
|
||||
out.String(string(jsonString))
|
||||
} else {
|
||||
|
@ -154,6 +174,13 @@ var printProfilesJSON = func() {
|
|||
}
|
||||
}
|
||||
|
||||
func profilesOrDefault(profiles []*config.Profile) []*config.Profile {
|
||||
if profiles != nil {
|
||||
return profiles
|
||||
}
|
||||
return []*config.Profile{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
profileListCmd.Flags().StringVarP(&output, "output", "o", "table", "The output format. One of 'json', 'table'")
|
||||
ProfileCmd.AddCommand(profileListCmd)
|
||||
|
|
|
@ -91,7 +91,6 @@ func init() {
|
|||
if err := viper.BindPFlags(deleteCmd.Flags()); err != nil {
|
||||
exit.Error(reason.InternalBindFlags, "unable to bind flags", err)
|
||||
}
|
||||
RootCmd.AddCommand(deleteCmd)
|
||||
}
|
||||
|
||||
// shotgun cleanup to delete orphaned docker container data
|
||||
|
@ -261,6 +260,11 @@ func deletePossibleKicLeftOver(cname string, driverName string) {
|
|||
glog.Warningf("error deleting volumes (might be okay).\nTo see the list of volumes run: 'docker volume ls'\n:%v", errs)
|
||||
}
|
||||
|
||||
errs = oci.DeleteKICNetworks()
|
||||
if errs != nil {
|
||||
glog.Warningf("error deleting leftover networks (might be okay).\nTo see the list of networks: 'docker network ls'\n:%v", errs)
|
||||
}
|
||||
|
||||
if bin == oci.Podman {
|
||||
// podman prune does not support --filter
|
||||
return
|
||||
|
|
|
@ -110,7 +110,7 @@ var mountCmd = &cobra.Command{
|
|||
var ip net.IP
|
||||
var err error
|
||||
if mountIP == "" {
|
||||
ip, err = cluster.HostIP(co.CP.Host)
|
||||
ip, err = cluster.HostIP(co.CP.Host, co.Config.Name)
|
||||
if err != nil {
|
||||
exit.Error(reason.IfHostIP, "Error getting the host IP address to use from within the VM", err)
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
gopshost "github.com/shirou/gopsutil/host"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
|
||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||
"k8s.io/minikube/pkg/minikube/bootstrapper/bsutil"
|
||||
|
@ -156,9 +157,14 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
out.WarningT("Profile name '{{.name}}' is not valid", out.V{"name": ClusterFlagValue()})
|
||||
exit.Message(reason.Usage, "Only alphanumeric and dashes '-' are permitted. Minimum 1 character, starting with alphanumeric.")
|
||||
}
|
||||
|
||||
existing, err := config.Load(ClusterFlagValue())
|
||||
if err != nil && !config.IsNotExist(err) {
|
||||
exit.Message(reason.HostConfigLoad, "Unable to load config: {{.error}}", out.V{"error": err})
|
||||
kind := reason.HostConfigLoad
|
||||
if config.IsPermissionDenied(err) {
|
||||
kind = reason.HostHomePermission
|
||||
}
|
||||
exit.Message(kind, "Unable to load config: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
||||
if existing != nil {
|
||||
|
@ -167,7 +173,24 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
|
||||
validateSpecifiedDriver(existing)
|
||||
validateKubernetesVersion(existing)
|
||||
|
||||
ds, alts, specified := selectDriver(existing)
|
||||
if cmd.Flag(kicBaseImage).Changed {
|
||||
if !isBaseImageApplicable(ds.Name) {
|
||||
exit.Message(reason.Usage,
|
||||
"flag --{{.imgFlag}} is not available for driver '{{.driver}}'. Did you mean to use '{{.docker}}' or '{{.podman}}' driver instead?\n"+
|
||||
"Please use --{{.isoFlag}} flag to configure VM based drivers",
|
||||
out.V{
|
||||
"imgFlag": kicBaseImage,
|
||||
"driver": ds.Name,
|
||||
"docker": registry.Docker,
|
||||
"podman": registry.Podman,
|
||||
"isoFlag": isoURL,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
starter, err := provisionWithDriver(cmd, ds, existing)
|
||||
if err != nil {
|
||||
node.ExitIfFatal(err)
|
||||
|
@ -516,6 +539,7 @@ func kubectlVersion(path string) (string, error) {
|
|||
return cv.ClientVersion.GitVersion, nil
|
||||
}
|
||||
|
||||
// returns (current_driver, suggested_drivers, "true, if the driver is set by command line arg or in the config file")
|
||||
func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []registry.DriverState, bool) {
|
||||
// Technically unrelated, but important to perform before detection
|
||||
driver.SetLibvirtURI(viper.GetString(kvmQemuURI))
|
||||
|
@ -770,7 +794,7 @@ func validateUser(drvName string) {
|
|||
|
||||
out.ErrT(style.Stopped, `The "{{.driver_name}}" driver should not be used with root privileges.`, out.V{"driver_name": drvName})
|
||||
out.ErrT(style.Tip, "If you are running minikube within a VM, consider using --driver=none:")
|
||||
out.ErrT(style.Documentation, " https://minikube.sigs.k8s.io/docs/reference/drivers/none/")
|
||||
out.ErrT(style.Documentation, " {{.url}}", out.V{"url": "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"})
|
||||
|
||||
cname := ClusterFlagValue()
|
||||
_, err = config.Load(cname)
|
||||
|
@ -805,7 +829,7 @@ func memoryLimits(drvName string) (int, int, error) {
|
|||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
containerLimit = int(s.TotalMemory / 1024 / 1024)
|
||||
containerLimit = util.ConvertBytesToMB(s.TotalMemory)
|
||||
}
|
||||
|
||||
return sysLimit, containerLimit, nil
|
||||
|
@ -1185,6 +1209,10 @@ func validateKubernetesVersion(old *config.ClusterConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
func isBaseImageApplicable(drv string) bool {
|
||||
return registry.IsKIC(drv)
|
||||
}
|
||||
|
||||
func getKubernetesVersion(old *config.ClusterConfig) string {
|
||||
paramVersion := viper.GetString(kubernetesVersion)
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
cfg "k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/proxy"
|
||||
)
|
||||
|
||||
|
@ -278,3 +280,33 @@ func TestSuggestMemoryAllocation(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseImageFlagDriverCombo(t *testing.T) {
|
||||
tests := []struct {
|
||||
driver string
|
||||
canUseBaseImg bool
|
||||
}{
|
||||
{driver.Docker, true},
|
||||
{driver.Podman, true},
|
||||
{driver.None, false},
|
||||
{driver.KVM2, false},
|
||||
{driver.VirtualBox, false},
|
||||
{driver.HyperKit, false},
|
||||
{driver.VMware, false},
|
||||
{driver.VMwareFusion, false},
|
||||
{driver.HyperV, false},
|
||||
{driver.Parallels, false},
|
||||
{"something_invalid", false},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.driver, func(t *testing.T) {
|
||||
got := isBaseImageApplicable(test.driver)
|
||||
if got != test.canUseBaseImg {
|
||||
t.Errorf("isBaseImageApplicable(driver=%v): got %v, expected %v",
|
||||
test.driver, got, test.canUseBaseImg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,6 @@ func init() {
|
|||
if err := viper.GetViper().BindPFlags(stopCmd.Flags()); err != nil {
|
||||
exit.Error(reason.InternalFlagsBind, "unable to bind flags", err)
|
||||
}
|
||||
|
||||
RootCmd.AddCommand(stopCmd)
|
||||
}
|
||||
|
||||
// runStop handles the executes the flow of "minikube stop"
|
||||
|
|
|
@ -45,5 +45,11 @@ var updateContextCmd = &cobra.Command{
|
|||
} else {
|
||||
out.T(style.Meh, `No changes required for the "{{.context}}" context`, out.V{"context": cname})
|
||||
}
|
||||
|
||||
if err := kubeconfig.SetCurrentContext(cname, kubeconfig.PathFromEnv()); err != nil {
|
||||
out.ErrT(style.Sad, `Error while setting kubectl current context: {{.error}}`, out.V{"error": err})
|
||||
} else {
|
||||
out.T(style.Kubectl, `Current context is "{{.context}}"`, out.V{"context": cname})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@ import (
|
|||
// Register drivers
|
||||
_ "k8s.io/minikube/pkg/minikube/registry/drvs"
|
||||
|
||||
// Force exp dependency
|
||||
_ "golang.org/x/exp/ebnf"
|
||||
|
||||
mlog "github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
|
|
@ -18,12 +18,17 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/perf/monitor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for {
|
||||
log.Print("~~~~~~~~~ Starting performance analysis ~~~~~~~~~~~~~~")
|
||||
if err := analyzePerformance(context.Background()); err != nil {
|
||||
log.Printf("error executing performance analysis: %v", err)
|
||||
}
|
||||
|
@ -36,5 +41,32 @@ func main() {
|
|||
// 2. running mkcmp against those PRs
|
||||
// 3. commenting results on those PRs
|
||||
func analyzePerformance(ctx context.Context) error {
|
||||
client := monitor.NewClient(ctx, monitor.GithubOwner, monitor.GithubRepo)
|
||||
prs, err := client.ListOpenPRsWithLabel(monitor.OkToTestLabel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "listing open prs")
|
||||
}
|
||||
log.Print("got prs:", prs)
|
||||
for _, pr := range prs {
|
||||
log.Printf("~~~ Analyzing PR %d ~~~", pr)
|
||||
newCommitsExist, err := client.NewCommitsExist(pr, monitor.BotName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !newCommitsExist {
|
||||
log.Println("New commits don't exist, skipping rerun...")
|
||||
continue
|
||||
}
|
||||
var message string
|
||||
message, err = monitor.RunMkcmp(ctx, pr)
|
||||
if err != nil {
|
||||
message = fmt.Sprintf("Error: %v\n%s", err, message)
|
||||
}
|
||||
log.Printf("message for pr %d:\n%s\n", pr, message)
|
||||
if err := client.CommentOnPR(pr, message); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Print("successfully commented on PR")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -131,10 +131,17 @@ metadata:
|
|||
app: gcp-auth
|
||||
webhooks:
|
||||
- name: gcp-auth-mutate.k8s.io
|
||||
failurePolicy: Fail
|
||||
objectSelector:
|
||||
matchExpressions:
|
||||
- key: gcp-auth-skip-secret
|
||||
operator: DoesNotExist
|
||||
namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: name
|
||||
operator: NotIn
|
||||
values:
|
||||
- kube-system
|
||||
sideEffects: None
|
||||
admissionReviewVersions: ["v1","v1beta1"]
|
||||
clientConfig:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Turn on Source Address Verification in all interfaces to
|
||||
# prevent some spoofing attacks.
|
||||
net.ipv4.conf.default.rp_filter=1
|
||||
net.ipv4.conf.all.rp_filter=1
|
|
@ -1,44 +1,125 @@
|
|||
# Copyright 2018 The Kubernetes Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# kind node base image
|
||||
#
|
||||
# For systemd + docker configuration used below, see the following references:
|
||||
# https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
|
||||
|
||||
# start from ubuntu 20.04, this image is reasonably small as a starting point
|
||||
# for a kubernetes node image, it doesn't contain much we don't need
|
||||
FROM ubuntu:focal-20200423
|
||||
|
||||
# copy in static files (configs, scripts)
|
||||
COPY 10-network-security.conf /etc/sysctl.d/10-network-security.conf
|
||||
COPY clean-install /usr/local/bin/clean-install
|
||||
COPY entrypoint /usr/local/bin/entrypoint
|
||||
|
||||
# Install dependencies, first from apt, then from release tarballs.
|
||||
# NOTE: we use one RUN to minimize layers.
|
||||
#
|
||||
# First we must ensure that our util scripts are executable.
|
||||
#
|
||||
# The base image already has: ssh, apt, snapd, but we need to install more packages.
|
||||
# Packages installed are broken down into (each on a line):
|
||||
# - packages needed to run services (systemd)
|
||||
# - packages needed for kubernetes components
|
||||
# - packages needed by the container runtime
|
||||
# - misc packages kind uses itself
|
||||
# After installing packages we cleanup by:
|
||||
# - removing unwanted systemd services
|
||||
# - disabling kmsg in journald (these log entries would be confusing)
|
||||
#
|
||||
# Next we ensure the /etc/kubernetes/manifests directory exists. Normally
|
||||
# a kubeadm debain / rpm package would ensure that this exists but we install
|
||||
# freshly built binaries directly when we build the node image.
|
||||
#
|
||||
# Finally we adjust tempfiles cleanup to be 1 minute after "boot" instead of 15m
|
||||
# This is plenty after we've done initial setup for a node, but before we are
|
||||
# likely to try to export logs etc.
|
||||
RUN echo "Ensuring scripts are executable ..." \
|
||||
&& chmod +x /usr/local/bin/clean-install /usr/local/bin/entrypoint \
|
||||
&& echo "Installing Packages ..." \
|
||||
&& DEBIAN_FRONTEND=noninteractive clean-install \
|
||||
systemd \
|
||||
conntrack iptables iproute2 ethtool socat util-linux mount ebtables udev kmod \
|
||||
libseccomp2 \
|
||||
bash ca-certificates curl rsync \
|
||||
&& find /lib/systemd/system/sysinit.target.wants/ -name "systemd-tmpfiles-setup.service" -delete \
|
||||
&& rm -f /lib/systemd/system/multi-user.target.wants/* \
|
||||
&& rm -f /etc/systemd/system/*.wants/* \
|
||||
&& rm -f /lib/systemd/system/local-fs.target.wants/* \
|
||||
&& rm -f /lib/systemd/system/sockets.target.wants/*udev* \
|
||||
&& rm -f /lib/systemd/system/sockets.target.wants/*initctl* \
|
||||
&& rm -f /lib/systemd/system/basic.target.wants/* \
|
||||
&& echo "ReadKMsg=no" >> /etc/systemd/journald.conf \
|
||||
&& ln -s "$(which systemd)" /sbin/init \
|
||||
&& echo "Ensuring /etc/kubernetes/manifests" \
|
||||
&& mkdir -p /etc/kubernetes/manifests \
|
||||
&& echo "Adjusting systemd-tmpfiles timer" \
|
||||
&& sed -i /usr/lib/systemd/system/systemd-tmpfiles-clean.timer -e 's#OnBootSec=.*#OnBootSec=1min#' \
|
||||
&& echo "Modifying /etc/nsswitch.conf to prefer hosts" \
|
||||
&& sed -i /etc/nsswitch.conf -re 's#^(hosts:\s*).*#\1dns files#'
|
||||
|
||||
# tell systemd that it is in docker (it will check for the container env)
|
||||
# https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
|
||||
ENV container docker
|
||||
# systemd exits on SIGRTMIN+3, not SIGTERM (which re-executes it)
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1201657
|
||||
STOPSIGNAL SIGRTMIN+3
|
||||
# NOTE: this is *only* for documentation, the entrypoint is overridden later
|
||||
ENTRYPOINT [ "/usr/local/bin/entrypoint", "/sbin/init" ]
|
||||
|
||||
ARG COMMIT_SHA
|
||||
# using base image created by kind https://github.com/kubernetes-sigs/kind/blob/v0.8.1/images/base/Dockerfile
|
||||
# using base image created by kind https://github.com/kubernetes-sigs/kind/blob/2c0eee40/images/base/Dockerfile
|
||||
# which is an ubuntu 20.04 with an entry-point that helps running systemd
|
||||
# could be changed to any debian that can run systemd
|
||||
FROM kindest/base:v20200430-2c0eee40 as base
|
||||
USER root
|
||||
# specify version of everything explicitly using 'apt-cache policy'
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
|
||||
# install system requirements from the regular distro repositories
|
||||
RUN clean-install \
|
||||
lz4 \
|
||||
gnupg \
|
||||
sudo \
|
||||
docker.io \
|
||||
containerd \
|
||||
openssh-server \
|
||||
dnsutils \
|
||||
runc \
|
||||
# libglib2.0-0 is required for conmon, which is required for podman
|
||||
libglib2.0-0 \
|
||||
# removing kind's crictl config
|
||||
&& rm /etc/crictl.yaml
|
||||
libglib2.0-0
|
||||
|
||||
# Install cri-o/podman dependencies:
|
||||
RUN sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list" && \
|
||||
curl -LO https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_20.04/Release.key && \
|
||||
apt-key add - < Release.key && apt-get update && \
|
||||
apt-get install -y --no-install-recommends containers-common catatonit conmon containernetworking-plugins podman-plugins varlink
|
||||
apt-key add - < Release.key && \
|
||||
clean-install containers-common catatonit conmon containernetworking-plugins cri-tools podman-plugins varlink
|
||||
|
||||
# install cri-o based on https://github.com/cri-o/cri-o/commit/96b0c34b31a9fc181e46d7d8e34fb8ee6c4dc4e1#diff-04c6e90faac2675aa89e2176d2eec7d8R128
|
||||
RUN sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.18:/1.18.3/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list" && \
|
||||
curl -LO https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.18:/1.18.3/xUbuntu_20.04/Release.key && \
|
||||
apt-key add - < Release.key && apt-get update && \
|
||||
apt-get install -y --no-install-recommends cri-o=1.18.3~3
|
||||
apt-key add - < Release.key && \
|
||||
clean-install cri-o=1.18.3~3
|
||||
|
||||
# install podman
|
||||
RUN sh -c "echo 'deb https://dl.bintray.com/afbjorklund/podman focal main' > /etc/apt/sources.list.d/podman.list" && \
|
||||
curl -L https://bintray.com/user/downloadSubjectPublicKey?username=afbjorklund -o afbjorklund-public.key.asc && \
|
||||
apt-key add - < afbjorklund-public.key.asc && apt-get update && \
|
||||
apt-get install -y --no-install-recommends podman=1.9.3~1
|
||||
apt-key add - < afbjorklund-public.key.asc && \
|
||||
clean-install podman=1.9.3~1
|
||||
|
||||
RUN mkdir -p /usr/lib/cri-o-runc/sbin && cp /usr/local/sbin/runc /usr/lib/cri-o-runc/sbin/runc
|
||||
RUN mkdir -p /usr/lib/cri-o-runc/sbin && cp /usr/sbin/runc /usr/lib/cri-o-runc/sbin/runc
|
||||
|
||||
COPY entrypoint /usr/local/bin/entrypoint
|
||||
# automount service
|
||||
COPY automount/minikube-automount /usr/sbin/minikube-automount
|
||||
COPY automount/minikube-automount.service /usr/lib/systemd/system/minikube-automount.service
|
||||
|
@ -71,12 +152,7 @@ USER root
|
|||
# https://github.com/kubernetes-sigs/kind/blob/master/images/base/files/usr/local/bin/entrypoint
|
||||
RUN mkdir -p /kind
|
||||
# Deleting leftovers
|
||||
RUN apt-get clean -y && rm -rf \
|
||||
/var/cache/debconf/* \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/log/* \
|
||||
/tmp/* \
|
||||
/var/tmp/* \
|
||||
RUN rm -rf \
|
||||
/usr/share/doc/* \
|
||||
/usr/share/man/* \
|
||||
/usr/share/local/* \
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright 2017 The Kubernetes Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# A script encapsulating a common Dockerimage pattern for installing packages
|
||||
# and then cleaning up the unnecessary install artifacts.
|
||||
# e.g. clean-install iptables ebtables conntrack
|
||||
|
||||
set -o errexit
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
echo >&2 "No packages specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends "$@"
|
||||
apt-get clean -y
|
||||
rm -rf \
|
||||
/var/cache/debconf/* \
|
||||
/var/lib/apt/lists/* \
|
||||
/var/log/* \
|
||||
/tmp/* \
|
||||
/var/tmp/* \
|
||||
/usr/share/doc/* \
|
||||
/usr/share/man/* \
|
||||
/usr/share/local/*
|
|
@ -1,4 +1,12 @@
|
|||
[
|
||||
{
|
||||
"name": "v1.13.1",
|
||||
"checksums": {
|
||||
"darwin": "cc7eaadea2becc48eee78136f8d569df55a28c46d58d1c8bb434895382aced78",
|
||||
"linux": "3564b685f8d797df78ebfa2f5b34c99b3c77b0d1f49eab6aab37500f1ba61d98",
|
||||
"windows": "0d315ec21ca8a34eff5fa4cc478c09ed2d48ae88b3c5d586df9de111ac414d44"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "v1.13.0",
|
||||
"checksums": {
|
||||
|
|
2
go.mod
2
go.mod
|
@ -28,6 +28,7 @@ require (
|
|||
github.com/google/go-cmp v0.4.1
|
||||
github.com/google/go-containerregistry v0.0.0-20200601195303-96cf69f03a3c
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/google/slowjam v0.0.0-20200530021616-df27e642fe7b
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/googleapis/gnostic v0.3.0 // indirect
|
||||
|
@ -72,6 +73,7 @@ require (
|
|||
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
|
||||
golang.org/x/build v0.0.0-20190927031335-2835ba2e683f
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121
|
||||
|
|
3
go.sum
3
go.sum
|
@ -517,6 +517,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
|
||||
|
@ -1204,6 +1206,7 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
|
|
|
@ -81,7 +81,7 @@ for path in $(gsutil ls "gs://${ISO_BUCKET}/minikube-v${VERSION}*" || true); do
|
|||
done
|
||||
|
||||
# Upload all end-user assets other than preload files, as they are release independent
|
||||
for file in out/minikube[_-]* out/docker-machine-*; do
|
||||
for file in $( find out \( -name "minikube[_-]*" -or -name "docker-machine-*" \) -and ! -name "*latest*"); do
|
||||
n=0
|
||||
until [ $n -ge 5 ]
|
||||
do
|
||||
|
|
|
@ -17,70 +17,156 @@ limitations under the License.
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/google/go-github/v32/github"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) == 1 {
|
||||
fmt.Println("Usage: go run update_kubernetes_version.go <kubernetes_version>")
|
||||
os.Exit(1)
|
||||
}
|
||||
// init glog: by default, all log statements write to files in a temporary directory, also
|
||||
// flag.Parse must be called before any logging is done
|
||||
flag.Parse()
|
||||
_ = flag.Set("logtostderr", "true")
|
||||
|
||||
v := os.Args[1]
|
||||
if !strings.HasPrefix(v, "v") {
|
||||
v = "v" + v
|
||||
}
|
||||
|
||||
constantsFile := "../../pkg/minikube/constants/constants.go"
|
||||
cf, err := ioutil.ReadFile(constantsFile)
|
||||
// fetch respective current stable (vDefault as DefaultKubernetesVersion) and
|
||||
// latest rc or beta (vDefault as NewestKubernetesVersion) Kubernetes GitHub Releases
|
||||
vDefault, vNewest, err := fetchKubernetesReleases()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
glog.Errorf("Fetching current GitHub Releases failed: %v", err)
|
||||
}
|
||||
if vDefault == "" || vNewest == "" {
|
||||
glog.Fatalf("Cannot determine current 'DefaultKubernetesVersion' and 'NewestKubernetesVersion'")
|
||||
}
|
||||
glog.Infof("Current Kubernetes GitHub Releases: 'stable' is %s and 'latest' is %s", vDefault, vNewest)
|
||||
|
||||
if err := updateKubernetesVersions(vDefault, vNewest); err != nil {
|
||||
glog.Fatalf("Updating 'DefaultKubernetesVersion' and 'NewestKubernetesVersion' failed: %v", err)
|
||||
}
|
||||
glog.Infof("Update successful: 'DefaultKubernetesVersion' was set to %s and 'NewestKubernetesVersion' was set to %s", vDefault, vNewest)
|
||||
|
||||
// Flush before exiting to guarantee all log output is written
|
||||
glog.Flush()
|
||||
}
|
||||
|
||||
// fetchKubernetesReleases returns respective current stable (as vDefault) and
|
||||
// latest rc or beta (as vNewest) Kubernetes GitHub Releases, and any error
|
||||
func fetchKubernetesReleases() (vDefault, vNewest string, err error) {
|
||||
client := github.NewClient(nil)
|
||||
|
||||
// set a context with a deadline - timeout after at most 10 seconds
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// walk through the paginated list of all 'kubernetes/kubernetes' repo releases
|
||||
// from latest to older releases, until latest release and pre-release are found
|
||||
// use max value (100) for PerPage to avoid hitting the rate limits (60 per hour, 10 per minute)
|
||||
// see https://godoc.org/github.com/google/go-github/github#hdr-Rate_Limiting
|
||||
opt := &github.ListOptions{PerPage: 100}
|
||||
for {
|
||||
rels, resp, err := client.Repositories.ListReleases(ctx, "kubernetes", "kubernetes", opt)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
for _, r := range rels {
|
||||
// GetName returns the Name field if it's non-nil, zero value otherwise.
|
||||
ver := r.GetName()
|
||||
if ver == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
rel := strings.Split(ver, "-")
|
||||
// check if it is a release channel (ie, 'v1.19.2') or a
|
||||
// pre-release channel (ie, 'v1.19.3-rc.0' or 'v1.19.0-beta.2')
|
||||
if len(rel) == 1 && vDefault == "" {
|
||||
vDefault = ver
|
||||
} else if len(rel) > 1 && vNewest == "" {
|
||||
if strings.HasPrefix(rel[1], "rc") || strings.HasPrefix(rel[1], "beta") {
|
||||
vNewest = ver
|
||||
}
|
||||
}
|
||||
|
||||
if vDefault != "" && vNewest != "" {
|
||||
// make sure that vNewest >= vDefault
|
||||
if vNewest < vDefault {
|
||||
vNewest = vDefault
|
||||
}
|
||||
return vDefault, vNewest, nil
|
||||
}
|
||||
}
|
||||
|
||||
if resp.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opt.Page = resp.NextPage
|
||||
}
|
||||
return vDefault, vNewest, nil
|
||||
}
|
||||
|
||||
// updateKubernetesVersions updates DefaultKubernetesVersion to vDefault release and
|
||||
// NewestKubernetesVersion to vNewest release, and returns any error
|
||||
func updateKubernetesVersions(vDefault, vNewest string) error {
|
||||
if err := replaceAllString("../../pkg/minikube/constants/constants.go", map[string]string{
|
||||
`DefaultKubernetesVersion = \".*`: "DefaultKubernetesVersion = \"" + vDefault + "\"",
|
||||
`NewestKubernetesVersion = \".*`: "NewestKubernetesVersion = \"" + vNewest + "\"",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := os.Stat(constantsFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
mode := info.Mode()
|
||||
|
||||
re := regexp.MustCompile(`DefaultKubernetesVersion = \".*`)
|
||||
f := re.ReplaceAllString(string(cf), "DefaultKubernetesVersion = \""+v+"\"")
|
||||
|
||||
re = regexp.MustCompile(`NewestKubernetesVersion = \".*`)
|
||||
f = re.ReplaceAllString(f, "NewestKubernetesVersion = \""+v+"\"")
|
||||
|
||||
if err := ioutil.WriteFile(constantsFile, []byte(f), mode); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
if err := replaceAllString("../../site/content/en/docs/commands/start.md", map[string]string{
|
||||
`'stable' for .*,`: "'stable' for " + vDefault + ",",
|
||||
`'latest' for .*\)`: "'latest' for " + vNewest + ")",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
testData := "../../pkg/minikube/bootstrapper/bsutil/testdata"
|
||||
// update testData just for the latest 'v<MAJOR>.<MINOR>.0' from vDefault
|
||||
vDefaultMM := vDefault[:strings.LastIndex(vDefault, ".")]
|
||||
testData := "../../pkg/minikube/bootstrapper/bsutil/testdata/" + vDefaultMM
|
||||
|
||||
err = filepath.Walk(testData, func(path string, info os.FileInfo, err error) error {
|
||||
return filepath.Walk(testData, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.HasSuffix(path, "default.yaml") {
|
||||
return nil
|
||||
}
|
||||
cf, err = ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
re = regexp.MustCompile(`kubernetesVersion: .*`)
|
||||
cf = []byte(re.ReplaceAllString(string(cf), "kubernetesVersion: "+v))
|
||||
return ioutil.WriteFile(path, cf, info.Mode())
|
||||
return replaceAllString(path, map[string]string{
|
||||
`kubernetesVersion: .*`: "kubernetesVersion: " + vDefaultMM + ".0",
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
glog.Errorf("Walk failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// replaceAllString replaces all occuranes of map's keys with their respective values in the file
|
||||
func replaceAllString(path string, pairs map[string]string) error {
|
||||
fb, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mode := info.Mode()
|
||||
|
||||
f := string(fb)
|
||||
for org, new := range pairs {
|
||||
re := regexp.MustCompile(org)
|
||||
f = re.ReplaceAllString(f, new)
|
||||
}
|
||||
if err := ioutil.WriteFile(path, []byte(f), mode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import (
|
|||
|
||||
func generateTarball(kubernetesVersion, containerRuntime, tarballFilename string) error {
|
||||
driver := kic.NewDriver(kic.Config{
|
||||
ClusterName: profile,
|
||||
KubernetesVersion: kubernetesVersion,
|
||||
ContainerRuntime: containerRuntime,
|
||||
OCIBinary: oci.Docker,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="702px" height="683px" viewBox="0 0 702 683" version="1.1" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 39.1 (31720) - https://www.sketchapp.com/ -->
|
||||
<svg width="702px" height="683px" viewBox="0 0 702 683" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>minikube</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
@ -324,7 +324,18 @@ func verifyAddonStatus(cc *config.ClusterConfig, name string, val string) error
|
|||
}
|
||||
|
||||
func verifyGCPAuthAddon(cc *config.ClusterConfig, name string, val string) error {
|
||||
return verifyAddonStatusInternal(cc, name, val, "gcp-auth")
|
||||
enable, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parsing bool: %s", name)
|
||||
}
|
||||
err = verifyAddonStatusInternal(cc, name, val, "gcp-auth")
|
||||
|
||||
if enable && err == nil {
|
||||
out.T(style.Notice, "Your GCP credentials will now be mounted into every pod created in the {{.name}} cluster.", out.V{"name": cc.Name})
|
||||
out.T(style.Notice, "If you don't want your credentials mounted into a specific pod, add a label with the `gcp-auth-skip-secret` key to your pod configuration.")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string, ns string) error {
|
||||
|
@ -394,16 +405,26 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo
|
|||
|
||||
var awg sync.WaitGroup
|
||||
|
||||
defer func() { // making it show after verifications( not perfect till #7613 is closed)
|
||||
enabledAddons := []string{}
|
||||
deferredAddons := []string{}
|
||||
|
||||
defer func() { // making it show after verifications (see #7613)
|
||||
register.Reg.SetStep(register.EnablingAddons)
|
||||
out.T(style.AddonEnable, "Enabled addons: {{.addons}}", out.V{"addons": strings.Join(toEnableList, ", ")})
|
||||
out.T(style.AddonEnable, "Enabled addons: {{.addons}}", out.V{"addons": strings.Join(enabledAddons, ", ")})
|
||||
}()
|
||||
for _, a := range toEnableList {
|
||||
if a == "gcp-auth" {
|
||||
deferredAddons = append(deferredAddons, a)
|
||||
continue
|
||||
}
|
||||
|
||||
awg.Add(1)
|
||||
go func(name string) {
|
||||
err := RunCallbacks(cc, name, "true")
|
||||
if err != nil {
|
||||
out.WarningT("Enabling '{{.name}}' returned an error: {{.error}}", out.V{"name": name, "error": err})
|
||||
} else {
|
||||
enabledAddons = append(enabledAddons, name)
|
||||
}
|
||||
awg.Done()
|
||||
}(a)
|
||||
|
@ -411,7 +432,18 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo
|
|||
|
||||
// Wait until all of the addons are enabled before updating the config (not thread safe)
|
||||
awg.Wait()
|
||||
for _, a := range toEnableList {
|
||||
|
||||
// Now run the deferred addons
|
||||
for _, a := range deferredAddons {
|
||||
err := RunCallbacks(cc, a, "true")
|
||||
if err != nil {
|
||||
out.WarningT("Enabling '{{.name}}' returned an error: {{.error}}", out.V{"name": a, "error": err})
|
||||
} else {
|
||||
enabledAddons = append(enabledAddons, a)
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range enabledAddons {
|
||||
if err := Set(cc, a, "true"); err != nil {
|
||||
glog.Errorf("store failed: %v", err)
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ var Addons = []*Addon{
|
|||
{
|
||||
name: "gcp-auth",
|
||||
set: SetBool,
|
||||
callbacks: []setFn{gcpauth.EnableOrDisable, enableOrDisableAddon, verifyGCPAuthAddon, gcpauth.DisplayAddonMessage},
|
||||
callbacks: []setFn{gcpauth.EnableOrDisable, enableOrDisableAddon, verifyGCPAuthAddon},
|
||||
},
|
||||
{
|
||||
name: "volumesnapshots",
|
||||
|
|
|
@ -60,7 +60,7 @@ func enableAddon(cfg *config.ClusterConfig) error {
|
|||
ctx := context.Background()
|
||||
creds, err := google.FindDefaultCredentials(ctx)
|
||||
if err != nil {
|
||||
exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.")
|
||||
exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.")
|
||||
}
|
||||
|
||||
f := assets.NewMemoryAssetTarget(creds.JSON, credentialsPath, "0444")
|
||||
|
@ -116,16 +116,3 @@ func disableAddon(cfg *config.ClusterConfig) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisplayAddonMessage display an gcp auth addon specific message to the user
|
||||
func DisplayAddonMessage(cfg *config.ClusterConfig, name string, val string) error {
|
||||
enable, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parsing bool: %s", name)
|
||||
}
|
||||
if enable {
|
||||
out.T(style.Notice, "Your GCP credentials will now be mounted into every pod created in the {{.name}} cluster.", out.V{"name": cfg.Name})
|
||||
out.T(style.Notice, "If you don't want your credentials mounted into a specific pod, add a label with the `gcp-auth-skip-secret` key to your pod configuration.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// This file is for common code shared among internal machine drivers
|
||||
|
@ -74,7 +75,7 @@ func createRawDiskImage(sshKeyPath, diskPath string, diskSizeMb int) error {
|
|||
return errors.Wrapf(err, "closing file %s", diskPath)
|
||||
}
|
||||
|
||||
if err := os.Truncate(diskPath, int64(diskSizeMb*1000000)); err != nil {
|
||||
if err := os.Truncate(diskPath, util.ConvertMBToBytes(diskSizeMb)); err != nil {
|
||||
return errors.Wrap(err, "truncate")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -36,7 +36,7 @@ func Test_createDiskImage(t *testing.T) {
|
|||
diskPath := filepath.Join(tmpdir, "disk")
|
||||
|
||||
sizeInMb := 100
|
||||
sizeInBytes := int64(sizeInMb) * 1000000
|
||||
sizeInBytes := int64(104857600)
|
||||
if err := createRawDiskImage(sshPath, diskPath, sizeInMb); err != nil {
|
||||
t.Errorf("createDiskImage() error = %v", err)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
)
|
||||
|
@ -81,6 +83,17 @@ func (d *Driver) Create() error {
|
|||
APIServerPort: d.NodeConfig.APIServerPort,
|
||||
}
|
||||
|
||||
if gateway, err := oci.CreateNetwork(d.OCIBinary, d.NodeConfig.ClusterName); err != nil {
|
||||
out.WarningT("Unable to create dedicated network, this might result in cluster IP change after restart: {{.error}}", out.V{"error": err})
|
||||
} else {
|
||||
params.Network = d.NodeConfig.ClusterName
|
||||
ip := gateway.To4()
|
||||
// calculate the container IP based on guessing the machine index
|
||||
ip[3] += byte(driver.IndexFromMachineName(d.NodeConfig.MachineName))
|
||||
glog.Infof("calculated static IP %q for the %q container", ip.String(), d.NodeConfig.MachineName)
|
||||
params.IP = ip.String()
|
||||
}
|
||||
|
||||
// control plane specific options
|
||||
params.PortMappings = append(params.PortMappings, oci.PortMapping{
|
||||
ListenAddress: oci.DefaultBindIPV4,
|
||||
|
@ -289,6 +302,10 @@ func (d *Driver) Remove() error {
|
|||
if id, err := oci.ContainerID(d.OCIBinary, d.MachineName); err == nil && id != "" {
|
||||
return fmt.Errorf("expected no container ID be found for %q after delete. but got %q", d.MachineName, id)
|
||||
}
|
||||
|
||||
if err := oci.RemoveNetwork(d.NodeConfig.ClusterName); err != nil {
|
||||
glog.Warningf("failed to remove network (which might be okay) %s: %v", d.NodeConfig.ClusterName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -403,7 +420,7 @@ func killAPIServerProc(runner command.Runner) error {
|
|||
pid, err := strconv.Atoi(rr.Stdout.String())
|
||||
if err == nil { // this means we have a valid pid
|
||||
glog.Warningf("Found a kube-apiserver running with pid %d, will try to kill the proc", pid)
|
||||
if _, err = runner.RunCmd(exec.Command("pkill", "-9", string(pid))); err != nil {
|
||||
if _, err = runner.RunCmd(exec.Command("pkill", "-9", fmt.Sprint(pid))); err != nil {
|
||||
return errors.Wrap(err, "kill")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,9 +144,11 @@ func runCmd(cmd *exec.Cmd, warnSlow ...bool) (*RunResult, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
rr.ExitCode = exitError.ExitCode()
|
||||
if ex, ok := err.(*exec.ExitError); ok {
|
||||
glog.Warningf("%s returned with exit code %d", rr.Command(), ex.ExitCode())
|
||||
rr.ExitCode = ex.ExitCode()
|
||||
}
|
||||
|
||||
// Decrease log spam
|
||||
if elapsed > (1 * time.Second) {
|
||||
glog.Infof("Completed: %s: (%s)", rr.Command(), elapsed)
|
||||
|
|
|
@ -39,12 +39,27 @@ var ErrWindowsContainers = &FailFastError{errors.New("docker container type is w
|
|||
// ErrCPUCountLimit is thrown when docker daemon doesn't have enough CPUs for the requested container
|
||||
var ErrCPUCountLimit = &FailFastError{errors.New("not enough CPUs is available for container")}
|
||||
|
||||
// ErrIPinUse is thrown when the container been given an IP used by another container
|
||||
var ErrIPinUse = &FailFastError{errors.New("can't create with that IP, address already in use")}
|
||||
|
||||
// ErrExitedUnexpectedly is thrown when container is created/started without error but later it exists and it's status is not running anymore.
|
||||
var ErrExitedUnexpectedly = errors.New("container exited unexpectedly")
|
||||
|
||||
// ErrDaemonInfo is thrown when docker/podman info is failing or not responding
|
||||
var ErrDaemonInfo = errors.New("daemon info not responding")
|
||||
|
||||
// ErrNetworkSubnetTaken is thrown when a subnet is taken by another network
|
||||
var ErrNetworkSubnetTaken = errors.New("subnet is taken")
|
||||
|
||||
// ErrNetworkNotFound is when given network was not found
|
||||
var ErrNetworkNotFound = errors.New("kic network not found")
|
||||
|
||||
// ErrNetworkGatewayTaken is when given network gatway is taken
|
||||
var ErrNetworkGatewayTaken = errors.New("network gateway is taken")
|
||||
|
||||
// ErrNetworkInUse is when trying to delete a network which is attached to another container
|
||||
var ErrNetworkInUse = errors.New("unable to delete a network that is attached to a running container")
|
||||
|
||||
// LogContainerDebug will print relevant docker/podman infos after a container fails
|
||||
func LogContainerDebug(ociBin string, name string) string {
|
||||
rr, err := containerInspect(ociBin, name)
|
||||
|
|
|
@ -22,20 +22,24 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SysInfo Info represents common system Information between docker and podman that minikube cares
|
||||
type SysInfo struct {
|
||||
CPUs int // CPUs is Number of CPUs
|
||||
TotalMemory int64 // TotalMemory Total available ram
|
||||
OSType string // container's OsType (windows or linux)
|
||||
Swarm bool // Weather or not the docker swarm is active
|
||||
StorageDriver string // the storage driver for the daemon (for example overlay2)
|
||||
CPUs int // CPUs is Number of CPUs
|
||||
TotalMemory int64 // TotalMemory Total available ram
|
||||
OSType string // container's OsType (windows or linux)
|
||||
Swarm bool // Weather or not the docker swarm is active
|
||||
StorageDriver string // the storage driver for the daemon (for example overlay2)
|
||||
Errors []string // any server issues
|
||||
}
|
||||
|
||||
var cachedSysInfo *SysInfo
|
||||
var cachedSysInfoErr *error
|
||||
var (
|
||||
cachedSysInfo *SysInfo
|
||||
cachedSysInfoErr *error
|
||||
)
|
||||
|
||||
// CachedDaemonInfo will run and return a docker/podman info only once per minikube run time. to avoid performance
|
||||
func CachedDaemonInfo(ociBin string) (SysInfo, error) {
|
||||
|
@ -58,7 +62,7 @@ func DaemonInfo(ociBin string) (SysInfo, error) {
|
|||
return *cachedSysInfo, err
|
||||
}
|
||||
d, err := dockerSystemInfo()
|
||||
cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType, Swarm: d.Swarm.LocalNodeState == "active", StorageDriver: d.Driver}
|
||||
cachedSysInfo = &SysInfo{CPUs: d.NCPU, TotalMemory: d.MemTotal, OSType: d.OSType, Swarm: d.Swarm.LocalNodeState == "active", StorageDriver: d.Driver, Errors: d.ServerErrors}
|
||||
return *cachedSysInfo, err
|
||||
}
|
||||
|
||||
|
@ -163,6 +167,7 @@ type dockerSysInfo struct {
|
|||
SecurityOptions []string `json:"SecurityOptions"`
|
||||
ProductLicense string `json:"ProductLicense"`
|
||||
Warnings interface{} `json:"Warnings"`
|
||||
ServerErrors []string
|
||||
ClientInfo struct {
|
||||
Debug bool `json:"Debug"`
|
||||
Plugins []interface{} `json:"Plugins"`
|
||||
|
@ -245,6 +250,7 @@ func dockerSystemInfo() (dockerSysInfo, error) {
|
|||
return ds, errors.Wrapf(err, "unmarshal docker system info")
|
||||
}
|
||||
|
||||
glog.Infof("docker info: %+v", ds)
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
|
@ -264,5 +270,6 @@ func podmanSystemInfo() (podmanSysInfo, error) {
|
|||
if err := json.Unmarshal([]byte(strings.TrimSpace(rawJSON)), &ps); err != nil {
|
||||
return ps, errors.Wrapf(err, "unmarshal podman system info")
|
||||
}
|
||||
glog.Infof("podman info: %+v", ps)
|
||||
return ps, nil
|
||||
}
|
||||
|
|
|
@ -31,17 +31,26 @@ import (
|
|||
|
||||
// RoutableHostIPFromInside returns the ip/dns of the host that container lives on
|
||||
// is routable from inside the container
|
||||
func RoutableHostIPFromInside(ociBin string, containerName string) (net.IP, error) {
|
||||
func RoutableHostIPFromInside(ociBin string, clusterName string, containerName string) (net.IP, error) {
|
||||
if ociBin == Docker {
|
||||
if runtime.GOOS == "linux" {
|
||||
return dockerGatewayIP(containerName)
|
||||
_, gateway, err := dockerNetworkInspect(clusterName)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNetworkNotFound) {
|
||||
glog.Infof("The container %s is not attached to a network, this could be because the cluster was created by minikube <v1.14, will try to get the IP using container gatway", containerName)
|
||||
|
||||
return containerGatewayIP(Docker, containerName)
|
||||
}
|
||||
return gateway, errors.Wrap(err, "network inspect")
|
||||
}
|
||||
return gateway, nil
|
||||
}
|
||||
// for windows and mac, the gateway ip is not routable so we use dns trick.
|
||||
return digDNS(ociBin, containerName, "host.docker.internal")
|
||||
}
|
||||
|
||||
// podman
|
||||
if runtime.GOOS == "linux" {
|
||||
return containerGatewayIP(ociBin, containerName)
|
||||
return containerGatewayIP(Podman, containerName)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("RoutableHostIPFromInside is currently only implemented for linux")
|
||||
|
@ -59,56 +68,8 @@ func digDNS(ociBin, containerName, dns string) (net.IP, error) {
|
|||
return ip, nil
|
||||
}
|
||||
|
||||
// profileInContainers checks whether the profile is within the containers list
|
||||
func profileInContainers(profile string, containers []string) bool {
|
||||
for _, container := range containers {
|
||||
if container == profile {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// dockerGatewayIP gets the default gateway ip for the docker bridge on the user's host machine
|
||||
// gets the ip from user's host docker
|
||||
func dockerGatewayIP(profile string) (net.IP, error) {
|
||||
var bridgeID string
|
||||
rr, err := runCmd(exec.Command(Docker, "network", "ls", "--filter", "name=bridge", "--format", "{{.ID}}"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get network bridge")
|
||||
}
|
||||
networksOutput := strings.TrimSpace(rr.Stdout.String())
|
||||
networksSlice := strings.Fields(networksOutput)
|
||||
// Look for the minikube container within each docker network
|
||||
for _, net := range networksSlice {
|
||||
// get all containers in the network
|
||||
rs, err := runCmd(exec.Command(Docker, "network", "inspect", net, "-f", "{{range $k, $v := .Containers}}{{$v.Name}} {{end}}"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get containers in network")
|
||||
}
|
||||
containersSlice := strings.Fields(rs.Stdout.String())
|
||||
if profileInContainers(profile, containersSlice) {
|
||||
bridgeID = net
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if bridgeID == "" {
|
||||
return nil, errors.Errorf("unable to determine bridge network id from %q", networksOutput)
|
||||
}
|
||||
rr, err = runCmd(exec.Command(Docker, "network", "inspect",
|
||||
"--format", "{{(index .IPAM.Config 0).Gateway}}", bridgeID))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "inspect IP bridge network %q.", bridgeID)
|
||||
}
|
||||
|
||||
ip := net.ParseIP(strings.TrimSpace(rr.Stdout.String()))
|
||||
glog.Infof("got host ip for mount in container by inspect docker network: %s", ip.String())
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// containerGatewayIP gets the default gateway ip for the container
|
||||
func containerGatewayIP(ociBin, containerName string) (net.IP, error) {
|
||||
func containerGatewayIP(ociBin string, containerName string) (net.IP, error) {
|
||||
rr, err := runCmd(exec.Command(ociBin, "container", "inspect", "--format", "{{.NetworkSettings.Gateway}}", containerName))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "inspect gateway")
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package oci
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// firstSubnetAddr subnet to be used on first kic cluster
|
||||
// it is one octet more than the one used by KVM to avoid possible conflict
|
||||
const firstSubnetAddr = "192.168.49.0"
|
||||
|
||||
// big enough for a cluster of 254 nodes
|
||||
const defaultSubnetMask = 24
|
||||
|
||||
// CreateNetwork creates a network returns gateway and error, minikube creates one network per cluster
|
||||
func CreateNetwork(ociBin string, name string) (net.IP, error) {
|
||||
if ociBin != Docker {
|
||||
return nil, fmt.Errorf("%s network not implemented yet", ociBin)
|
||||
}
|
||||
return createDockerNetwork(name)
|
||||
}
|
||||
|
||||
func createDockerNetwork(clusterName string) (net.IP, error) {
|
||||
// check if the network already exists
|
||||
subnet, gateway, err := dockerNetworkInspect(clusterName)
|
||||
if err == nil {
|
||||
glog.Infof("Found existing network with subnet %s and gateway %s.", subnet, gateway)
|
||||
return gateway, nil
|
||||
}
|
||||
|
||||
attempts := 0
|
||||
subnetAddr := firstSubnetAddr
|
||||
// Rather than iterate through all of the valid subnets, give up at 20 to avoid a lengthy user delay for something that is unlikely to work.
|
||||
// will be like 192.168.49.0/24 ,...,192.168.239.0/24
|
||||
for attempts < 20 {
|
||||
gateway, err = tryCreateDockerNetwork(subnetAddr, defaultSubnetMask, clusterName)
|
||||
if err == nil {
|
||||
return gateway, nil
|
||||
}
|
||||
|
||||
// don't retry if error is not adddress is taken
|
||||
if !(errors.Is(err, ErrNetworkSubnetTaken) || errors.Is(err, ErrNetworkGatewayTaken)) {
|
||||
glog.Errorf("error while trying to create network %v", err)
|
||||
return nil, errors.Wrap(err, "un-retryable")
|
||||
}
|
||||
attempts++
|
||||
// Find an open subnet by incrementing the 3rd octet by 10 for each try
|
||||
// 13 times adding 10 firstSubnetAddr "192.168.49.0/24"
|
||||
// at most it will add up to 169 which is still less than max allowed 255
|
||||
// this is large enough to try more and not too small to not try enough
|
||||
// can be tuned in the next iterations
|
||||
newSubnet := net.ParseIP(subnetAddr).To4()
|
||||
newSubnet[2] += byte(9 + attempts)
|
||||
subnetAddr = newSubnet.String()
|
||||
}
|
||||
return gateway, fmt.Errorf("failed to create network after 20 attempts")
|
||||
}
|
||||
|
||||
func tryCreateDockerNetwork(subnetAddr string, subnetMask int, name string) (net.IP, error) {
|
||||
gateway := net.ParseIP(subnetAddr)
|
||||
gateway.To4()[3]++ // first ip for gateway
|
||||
glog.Infof("attempt to create network %s/%d with subnet: %s and gateway %s...", subnetAddr, subnetMask, name, gateway)
|
||||
// options documentation https://docs.docker.com/engine/reference/commandline/network_create/#bridge-driver-options
|
||||
rr, err := runCmd(exec.Command(Docker, "network", "create", "--driver=bridge", fmt.Sprintf("--subnet=%s", fmt.Sprintf("%s/%d", subnetAddr, subnetMask)), fmt.Sprintf("--gateway=%s", gateway), "-o", "--ip-masq", "-o", "--icc", fmt.Sprintf("--label=%s=%s", CreatedByLabelKey, "true"), name))
|
||||
if err != nil {
|
||||
// Pool overlaps with other one on this address space
|
||||
if strings.Contains(rr.Output(), "Pool overlaps") {
|
||||
return nil, ErrNetworkSubnetTaken
|
||||
}
|
||||
if strings.Contains(rr.Output(), "failed to allocate gateway") && strings.Contains(rr.Output(), "Address already in use") {
|
||||
return nil, ErrNetworkGatewayTaken
|
||||
}
|
||||
return nil, errors.Wrapf(err, "create network %s", fmt.Sprintf("%s %s/%d", name, subnetAddr, subnetMask))
|
||||
}
|
||||
return gateway, nil
|
||||
}
|
||||
|
||||
// returns subnet and gate if exists
|
||||
func dockerNetworkInspect(name string) (*net.IPNet, net.IP, error) {
|
||||
rr, err := runCmd(exec.Command(Docker, "network", "inspect", name, "--format", "{{(index .IPAM.Config 0).Subnet}},{{(index .IPAM.Config 0).Gateway}}"))
|
||||
if err != nil {
|
||||
if strings.Contains(rr.Output(), "No such network") {
|
||||
return nil, nil, ErrNetworkNotFound
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
// results looks like 172.17.0.0/16,172.17.0.1
|
||||
ips := strings.Split(strings.TrimSpace(rr.Stdout.String()), ",")
|
||||
if len(ips) == 0 {
|
||||
return nil, nil, fmt.Errorf("empty IP list parsed from: %q", rr.Output())
|
||||
}
|
||||
|
||||
_, subnet, err := net.ParseCIDR(ips[0])
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "parse subnet for %s", name)
|
||||
}
|
||||
var gateway net.IP
|
||||
if len(ips) > 0 {
|
||||
gateway = net.ParseIP(ips[1])
|
||||
}
|
||||
return subnet, gateway, nil
|
||||
}
|
||||
|
||||
// RemoveNetwork removes a network
|
||||
func RemoveNetwork(name string) error {
|
||||
if !networkExists(name) {
|
||||
return nil
|
||||
}
|
||||
rr, err := runCmd(exec.Command(Docker, "network", "remove", name))
|
||||
if err != nil {
|
||||
if strings.Contains(rr.Output(), "No such network") {
|
||||
return ErrNetworkNotFound
|
||||
}
|
||||
// Error response from daemon: error while removing network: network mynet123 id f9e1c50b89feb0b8f4b687f3501a81b618252c9907bc20666e386d0928322387 has active endpoints
|
||||
if strings.Contains(rr.Output(), "has active endpoints") {
|
||||
return ErrNetworkInUse
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func networkExists(name string) bool {
|
||||
_, _, err := dockerNetworkInspect(name)
|
||||
if err != nil && !errors.Is(err, ErrNetworkNotFound) { // log unexpected error
|
||||
glog.Warningf("Error inspecting docker network %s: %v", name, err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// networkNamesByLabel returns all network names created by a label
|
||||
func networkNamesByLabel(ociBin string, label string) ([]string, error) {
|
||||
if ociBin != Docker {
|
||||
return nil, fmt.Errorf("%s not supported", ociBin)
|
||||
}
|
||||
|
||||
// docker network ls --filter='label=created_by.minikube.sigs.k8s.io=true' --format '{{.Name}}'
|
||||
rr, err := runCmd(exec.Command(Docker, "network", "ls", fmt.Sprintf("--filter=label=%s", label), "--format", "{{.Name}}"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(bytes.NewReader(rr.Stdout.Bytes()))
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, strings.TrimSpace(scanner.Text()))
|
||||
}
|
||||
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
// DeleteKICNetworks deletes all networks created by kic
|
||||
func DeleteKICNetworks() []error {
|
||||
var errs []error
|
||||
ns, err := networkNamesByLabel(Docker, CreatedByLabelKey+"=true")
|
||||
if err != nil {
|
||||
return []error{errors.Wrap(err, "list all volume")}
|
||||
}
|
||||
for _, n := range ns {
|
||||
err := RemoveNetwork(n)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -169,6 +169,11 @@ func CreateContainerNode(p CreateParams) error {
|
|||
virtualization = "podman" // VIRTUALIZATION_PODMAN
|
||||
}
|
||||
if p.OCIBinary == Docker {
|
||||
// to provide a static IP for docker
|
||||
if p.Network != "" && p.IP != "" {
|
||||
runArgs = append(runArgs, "--network", p.Network)
|
||||
runArgs = append(runArgs, "--ip", p.IP)
|
||||
}
|
||||
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var", p.Name))
|
||||
// ignore apparmore github actions docker: https://github.com/kubernetes/minikube/issues/7624
|
||||
runArgs = append(runArgs, "--security-opt", "apparmor=unconfined")
|
||||
|
@ -285,6 +290,10 @@ func createContainer(ociBin string, image string, opts ...createOpt) error {
|
|||
if strings.Contains(rr.Output(), "Range of CPUs is from") && strings.Contains(rr.Output(), "CPUs available") { // CPUs available
|
||||
return ErrCPUCountLimit
|
||||
}
|
||||
// example: docker: Error response from daemon: Address already in use.
|
||||
if strings.Contains(rr.Output(), "Address already in use") {
|
||||
return ErrIPinUse
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ const (
|
|||
|
||||
// CreateParams are parameters needed to create a container
|
||||
type CreateParams struct {
|
||||
ClusterName string // cluster(profile name) that this container belongs to
|
||||
Name string // used for container name and hostname
|
||||
Image string // container image to use to create the node.
|
||||
ClusterLabel string // label the clusters we create using minikube so we can clean up
|
||||
|
@ -56,6 +57,8 @@ type CreateParams struct {
|
|||
Envs map[string]string // environment variables to pass to the container
|
||||
ExtraArgs []string // a list of any extra option to pass to oci binary during creation time, for example --expose 8080...
|
||||
OCIBinary string // docker or podman
|
||||
Network string // network name that the container will attach to
|
||||
IP string // static IP to assign for th container in the cluster network
|
||||
}
|
||||
|
||||
// createOpt is an option for Create
|
||||
|
|
|
@ -24,9 +24,9 @@ import (
|
|||
|
||||
const (
|
||||
// Version is the current version of kic
|
||||
Version = "v0.0.12-snapshot3"
|
||||
Version = "v0.0.13-snapshot1"
|
||||
// SHA of the kic base image
|
||||
baseImageSHA = "1d687ba53e19dbe5fafe4cc18aa07f269ecc4b7b622f2251b5bf569ddb474e9b"
|
||||
baseImageSHA = "4d43acbd0050148d4bc399931f1b15253b5e73815b63a67b8ab4a5c9e523403f"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -48,6 +48,7 @@ var (
|
|||
|
||||
// Config is configuration for the kic driver used by registry
|
||||
type Config struct {
|
||||
ClusterName string // The cluster the container belongs to
|
||||
MachineName string // maps to the container name being created
|
||||
CPU int // Number of CPU cores assigned to the container
|
||||
Memory int // max memory in MB
|
||||
|
|
|
@ -31,8 +31,8 @@ import (
|
|||
|
||||
const domainTmpl = `
|
||||
<domain type='kvm'>
|
||||
<name>{{.MachineName}}</name>
|
||||
<memory unit='MB'>{{.Memory}}</memory>
|
||||
<name>{{.MachineName}}</name>
|
||||
<memory unit='MiB'>{{.Memory}}</memory>
|
||||
<vcpu>{{.CPU}}</vcpu>
|
||||
<features>
|
||||
<acpi/>
|
||||
|
|
|
@ -34,12 +34,12 @@ import (
|
|||
)
|
||||
|
||||
// HostIP gets the ip address to be used for mapping host -> VM and VM -> host
|
||||
func HostIP(host *host.Host) (net.IP, error) {
|
||||
func HostIP(host *host.Host, clusterName string) (net.IP, error) {
|
||||
switch host.DriverName {
|
||||
case driver.Docker:
|
||||
return oci.RoutableHostIPFromInside(oci.Docker, host.Name)
|
||||
return oci.RoutableHostIPFromInside(oci.Docker, clusterName, host.Name)
|
||||
case driver.Podman:
|
||||
return oci.RoutableHostIPFromInside(oci.Podman, host.Name)
|
||||
return oci.RoutableHostIPFromInside(oci.Podman, clusterName, host.Name)
|
||||
case driver.KVM2:
|
||||
return net.ParseIP("192.168.39.1"), nil
|
||||
case driver.HyperV:
|
||||
|
@ -49,6 +49,7 @@ func HostIP(host *host.Host) (net.IP, error) {
|
|||
for i := 0; i < v.NumField(); i++ {
|
||||
if v.Type().Field(i).Name == "VSwitch" {
|
||||
hypervVirtualSwitch = v.Field(i).Interface().(string)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +60,7 @@ func HostIP(host *host.Host) (net.IP, error) {
|
|||
if err != nil {
|
||||
return []byte{}, errors.Wrap(err, fmt.Sprintf("ip for interface (%s)", hypervVirtualSwitch))
|
||||
}
|
||||
|
||||
return ip, nil
|
||||
case driver.VirtualBox:
|
||||
vBoxManageCmd := driver.VBoxManagePath()
|
||||
|
@ -74,6 +76,7 @@ func HostIP(host *host.Host) (net.IP, error) {
|
|||
}
|
||||
re = regexp.MustCompile(`(?sm)Name:\s*` + iface + `\s*$.+?IPAddress:\s*(\S+)`)
|
||||
ip := re.FindStringSubmatch(string(ipList))[1]
|
||||
|
||||
return net.ParseIP(ip), nil
|
||||
case driver.Parallels:
|
||||
bin := "prlsrvctl"
|
||||
|
@ -93,6 +96,7 @@ func HostIP(host *host.Host) (net.IP, error) {
|
|||
return []byte{}, errors.Wrap(err, "Error getting the IP address of Parallels Shared network interface")
|
||||
}
|
||||
ip := ipMatch[1]
|
||||
|
||||
return net.ParseIP(ip), nil
|
||||
case driver.HyperKit:
|
||||
return net.ParseIP("192.168.64.1"), nil
|
||||
|
@ -136,6 +140,7 @@ func DriverIP(api libmachine.API, machineName string) (net.IP, error) {
|
|||
|
||||
// Based on code from http://stackoverflow.com/questions/23529663/how-to-get-all-addresses-and-masks-from-local-interfaces-in-go
|
||||
func getIPForInterface(name string) (net.IP, error) {
|
||||
glog.Infof("getIPForInterface: searching for %q", name)
|
||||
ints, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -143,19 +148,25 @@ func getIPForInterface(name string) (net.IP, error) {
|
|||
|
||||
var i net.Interface
|
||||
for _, in := range ints {
|
||||
if strings.HasPrefix(in.Name, name) {
|
||||
if strings.HasPrefix(strings.ToLower(in.Name), strings.ToLower(name)) {
|
||||
glog.Infof("found prefix matching interface for %q: %q", name, in.Name)
|
||||
i = in
|
||||
|
||||
break
|
||||
}
|
||||
glog.Infof("%q does not match prefix %q", in.Name, name)
|
||||
}
|
||||
|
||||
// Didn't find prefix, let's try any substring
|
||||
if i.Name == "" {
|
||||
for _, in := range ints {
|
||||
if strings.Contains(in.Name, name) {
|
||||
if strings.Contains(strings.ToLower(in.Name), strings.ToLower(name)) {
|
||||
glog.Infof("found substring matching interface for %q: %q", name, in.Name)
|
||||
i = in
|
||||
|
||||
break
|
||||
}
|
||||
glog.Infof("%q does not match substring %q", in.Name, name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,14 +175,15 @@ func getIPForInterface(name string) (net.IP, error) {
|
|||
return nil, errors.Errorf("Could not find interface %s inside %+v", name, ints)
|
||||
}
|
||||
|
||||
glog.Infof("Found hyperv interface: %+v\n", i)
|
||||
glog.Infof("Found interface: %+v\n", i)
|
||||
addrs, _ := i.Addrs()
|
||||
for _, a := range addrs {
|
||||
glog.Infof("interface addr: %+v", a)
|
||||
if ipnet, ok := a.(*net.IPNet); ok {
|
||||
if ip := ipnet.IP.To4(); ip != nil {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, errors.Errorf("Error finding IPV4 address for %s", name)
|
||||
return nil, errors.Errorf("Unable to find a IPv4 address for interface %q", name)
|
||||
}
|
||||
|
|
|
@ -80,6 +80,24 @@ func IsNotExist(err error) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ErrPermissionDenied is the error returned when the config cannot be read
|
||||
// due to insufficient permissions
|
||||
type ErrPermissionDenied struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (e *ErrPermissionDenied) Error() string {
|
||||
return e.s
|
||||
}
|
||||
|
||||
// IsPermissionDenied returns whether the error is a ErrPermissionDenied instance
|
||||
func IsPermissionDenied(err error) bool {
|
||||
if _, ok := err.(*ErrPermissionDenied); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MinikubeConfig represents minikube config
|
||||
type MinikubeConfig map[string]interface{}
|
||||
|
||||
|
@ -184,6 +202,9 @@ func (c *simpleConfigLoader) LoadConfigFromFile(profileName string, miniHome ...
|
|||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return nil, &ErrPermissionDenied{err.Error()}
|
||||
}
|
||||
return nil, errors.Wrap(err, "read")
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
@ -297,3 +298,15 @@ func MachineName(cc config.ClusterConfig, n config.Node) string {
|
|||
}
|
||||
return fmt.Sprintf("%s-%s", cc.Name, n.Name)
|
||||
}
|
||||
|
||||
// IndexFromMachineName returns the order of the container based on it is name
|
||||
func IndexFromMachineName(machineName string) int {
|
||||
// minikube-m02
|
||||
sp := strings.Split(machineName, "-")
|
||||
m := strings.Trim(sp[len(sp)-1], "m") // m02
|
||||
i, err := strconv.Atoi(m)
|
||||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/registry"
|
||||
)
|
||||
|
||||
|
@ -201,3 +202,160 @@ func TestSuggest(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineName(t *testing.T) {
|
||||
testsCases := []struct {
|
||||
ClusterConfig config.ClusterConfig
|
||||
Want string
|
||||
}{
|
||||
{
|
||||
ClusterConfig: config.ClusterConfig{Name: "minikube",
|
||||
Nodes: []config.Node{
|
||||
config.Node{
|
||||
Name: "",
|
||||
IP: "172.17.0.3",
|
||||
Port: 8443,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: true,
|
||||
Worker: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Want: "minikube",
|
||||
},
|
||||
|
||||
{
|
||||
ClusterConfig: config.ClusterConfig{Name: "p2",
|
||||
Nodes: []config.Node{
|
||||
config.Node{
|
||||
Name: "",
|
||||
IP: "172.17.0.3",
|
||||
Port: 8443,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: true,
|
||||
Worker: true,
|
||||
},
|
||||
config.Node{
|
||||
Name: "m2",
|
||||
IP: "172.17.0.4",
|
||||
Port: 0,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: false,
|
||||
Worker: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Want: "p2-m2",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testsCases {
|
||||
got := MachineName(tc.ClusterConfig, tc.ClusterConfig.Nodes[len(tc.ClusterConfig.Nodes)-1])
|
||||
if got != tc.Want {
|
||||
t.Errorf("Expected MachineName to be %q but got %q", tc.Want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndexFromMachineName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
MachineName string
|
||||
Want int
|
||||
}{
|
||||
{
|
||||
Name: "default",
|
||||
MachineName: "minikube",
|
||||
Want: 1},
|
||||
{
|
||||
Name: "second-node",
|
||||
MachineName: "minikube-m02",
|
||||
Want: 2},
|
||||
{
|
||||
Name: "funny",
|
||||
MachineName: "hahaha",
|
||||
Want: 1},
|
||||
|
||||
{
|
||||
Name: "dash-profile",
|
||||
MachineName: "my-dashy-minikube",
|
||||
Want: 1},
|
||||
|
||||
{
|
||||
Name: "dash-profile-second-node",
|
||||
MachineName: "my-dashy-minikube-m02",
|
||||
Want: 2},
|
||||
{
|
||||
Name: "michivious-user",
|
||||
MachineName: "michivious-user-m02-m03",
|
||||
Want: 3},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
got := IndexFromMachineName(tc.MachineName)
|
||||
if got != tc.Want {
|
||||
t.Errorf("want order %q but got %q", tc.Want, got)
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// test indexFroMachine against cluster config
|
||||
func TestIndexFromMachineNameClusterConfig(t *testing.T) {
|
||||
|
||||
testsCases := []struct {
|
||||
ClusterConfig config.ClusterConfig
|
||||
Want int
|
||||
}{
|
||||
{
|
||||
ClusterConfig: config.ClusterConfig{Name: "minikube",
|
||||
Nodes: []config.Node{
|
||||
config.Node{
|
||||
Name: "",
|
||||
IP: "172.17.0.3",
|
||||
Port: 8443,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: true,
|
||||
Worker: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Want: 1,
|
||||
},
|
||||
|
||||
{
|
||||
ClusterConfig: config.ClusterConfig{Name: "p2",
|
||||
Nodes: []config.Node{
|
||||
config.Node{
|
||||
Name: "",
|
||||
IP: "172.17.0.3",
|
||||
Port: 8443,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: true,
|
||||
Worker: true,
|
||||
},
|
||||
config.Node{
|
||||
Name: "m2",
|
||||
IP: "172.17.0.4",
|
||||
Port: 0,
|
||||
KubernetesVersion: "v1.19.2",
|
||||
ControlPlane: false,
|
||||
Worker: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Want: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testsCases {
|
||||
got := IndexFromMachineName(MachineName(tc.ClusterConfig, tc.ClusterConfig.Nodes[len(tc.ClusterConfig.Nodes)-1]))
|
||||
if got != tc.Want {
|
||||
t.Errorf("expected IndexFromMachineName to be %d but got %d", tc.Want, got)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import (
|
|||
var exclude = []string{
|
||||
"{{.error}}",
|
||||
"{{.url}}",
|
||||
" {{.url}}",
|
||||
"{{.msg}}: {{.err}}",
|
||||
"{{.key}}={{.value}}",
|
||||
"opt {{.docker_option}}",
|
||||
|
@ -50,6 +51,7 @@ var exclude = []string{
|
|||
"\\n",
|
||||
"==\u003e {{.name}} \u003c==",
|
||||
"- {{.profile}}",
|
||||
" - {{.profile}}",
|
||||
}
|
||||
|
||||
// ErrMapFile is a constant to refer to the err_map file, which contains the Advice strings.
|
||||
|
@ -333,9 +335,6 @@ func checkString(s string) string {
|
|||
// Parse out quote marks
|
||||
stringToTranslate := s[1 : len(s)-1]
|
||||
|
||||
// Trim whitespace
|
||||
stringToTranslate = strings.TrimSpace(stringToTranslate)
|
||||
|
||||
// Don't translate integers
|
||||
if _, err := strconv.Atoi(stringToTranslate); err == nil {
|
||||
return ""
|
||||
|
|
|
@ -40,27 +40,27 @@ func MaybeDisplayAdvice(err error, driver string) {
|
|||
if errors.Is(err, oci.ErrExitedUnexpectedly) || errors.Is(err, oci.ErrDaemonInfo) {
|
||||
out.T(style.Tip, "If you are still interested to make {{.driver_name}} driver work. The following suggestions might help you get passed this issue:", out.V{"driver_name": driver})
|
||||
if driver == oci.Docker || driver == oci.Podman {
|
||||
out.T(style.Empty, `
|
||||
- Prune unused {{.driver_name}} images, volumes, networks and abandoned containers.
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Prune unused {{.driver_name}} images, volumes, networks and abandoned containers.
|
||||
|
||||
{{.driver_name}} system prune --volumes`, out.V{"driver_name": driver})
|
||||
{{.driver_name}} system prune --volumes`, out.V{"driver_name": driver})
|
||||
}
|
||||
out.T(style.Empty, `
|
||||
- Restart your {{.driver_name}} service`, out.V{"driver_name": driver})
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Restart your {{.driver_name}} service`, out.V{"driver_name": driver})
|
||||
if runtime.GOOS != "linux" {
|
||||
out.T(style.Empty, `
|
||||
- Ensure your {{.driver_name}} daemon has access to enough CPU/memory resources. `, out.V{"driver_name": driver})
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Ensure your {{.driver_name}} daemon has access to enough CPU/memory resources.`, out.V{"driver_name": driver})
|
||||
if runtime.GOOS == "darwin" && driver == oci.Docker {
|
||||
out.T(style.Empty, `
|
||||
- Docs https://docs.docker.com/docker-for-mac/#resources`, out.V{"driver_name": driver})
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Docs https://docs.docker.com/docker-for-mac/#resources`, out.V{"driver_name": driver})
|
||||
}
|
||||
if runtime.GOOS == "windows" && driver == oci.Docker {
|
||||
out.T(style.Empty, `
|
||||
- Docs https://docs.docker.com/docker-for-windows/#resources`, out.V{"driver_name": driver})
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Docs https://docs.docker.com/docker-for-windows/#resources`, out.V{"driver_name": driver})
|
||||
}
|
||||
}
|
||||
out.T(style.Empty, `
|
||||
- Delete and recreate minikube cluster
|
||||
out.String("\n\t")
|
||||
out.T(style.Empty, `- Delete and recreate minikube cluster
|
||||
minikube delete
|
||||
minikube start --driver={{.driver_name}}`, out.V{"driver_name": driver})
|
||||
// TODO #8348: maybe advice user if to set the --force-systemd https://github.com/kubernetes/minikube/issues/8348
|
||||
|
|
|
@ -46,7 +46,7 @@ func deleteOrphanedKIC(ociBin string, name string) {
|
|||
glog.Infof("couldn't inspect container %q before deleting: %v", name, err)
|
||||
return
|
||||
}
|
||||
// allow no more than 5 seconds for delting the container
|
||||
// allow no more than 5 seconds for deleting the container
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/out/register"
|
||||
"k8s.io/minikube/pkg/minikube/style"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// HostInfo holds information on the user's machine
|
||||
|
@ -38,10 +39,6 @@ type HostInfo struct {
|
|||
DiskSize int64
|
||||
}
|
||||
|
||||
func megs(bytes uint64) int64 {
|
||||
return int64(bytes / 1024 / 1024)
|
||||
}
|
||||
|
||||
// CachedHostInfo returns system information such as memory,CPU, DiskSize
|
||||
func CachedHostInfo() (*HostInfo, error, error, error) {
|
||||
var cpuErr, memErr, diskErr error
|
||||
|
@ -61,8 +58,8 @@ func CachedHostInfo() (*HostInfo, error, error, error) {
|
|||
|
||||
var info HostInfo
|
||||
info.CPUs = len(i)
|
||||
info.Memory = megs(v.Total)
|
||||
info.DiskSize = megs(d.Total)
|
||||
info.Memory = util.ConvertUnsignedBytesToMB(v.Total)
|
||||
info.DiskSize = util.ConvertUnsignedBytesToMB(d.Total)
|
||||
return &info, cpuErr, memErr, diskErr
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down
|
|||
// If we end up using a fallback image, notify the user
|
||||
defer func() {
|
||||
if finalImg != "" && finalImg != baseImg {
|
||||
out.WarningT(fmt.Sprintf("minikube was unable to download %s, but successfully downloaded %s as a fallback image", image.Tag(cc.KicBaseImage), image.Tag(finalImg)))
|
||||
out.WarningT(fmt.Sprintf("minikube was unable to download %s, but successfully downloaded %s as a fallback image", image.Tag(baseImg), image.Tag(finalImg)))
|
||||
cc.KicBaseImage = finalImg
|
||||
}
|
||||
}()
|
||||
|
@ -136,7 +136,7 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down
|
|||
glog.Infof("successfully loaded %s from cached tarball", img)
|
||||
// strip the digest from the img before saving it in the config
|
||||
// because loading an image from tarball to daemon doesn't load the digest
|
||||
finalImg = image.Tag(img)
|
||||
finalImg = img
|
||||
return nil
|
||||
}
|
||||
glog.Infof("Downloading %s to local daemon", img)
|
||||
|
|
|
@ -94,7 +94,7 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) {
|
|||
showVersionInfo(starter.Node.KubernetesVersion, cr)
|
||||
|
||||
// Add "host.minikube.internal" DNS alias (intentionally non-fatal)
|
||||
hostIP, err := cluster.HostIP(starter.Host)
|
||||
hostIP, err := cluster.HostIP(starter.Host, starter.Cfg.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("Unable to get host IP: %v", err)
|
||||
} else if err := machine.AddHostAlias(starter.Runner, constants.HostAlias, hostIP); err != nil {
|
||||
|
@ -311,7 +311,7 @@ func setupKubeAdm(mAPI libmachine.API, cfg config.ClusterConfig, n config.Node,
|
|||
func setupKubeconfig(h *host.Host, cc *config.ClusterConfig, n *config.Node, clusterName string) *kubeconfig.Settings {
|
||||
addr, err := apiServerURL(*h, *cc, *n)
|
||||
if err != nil {
|
||||
exit.Error(reason.DrvCPEndpoint, "Failed to get API Server URL", err)
|
||||
exit.Message(reason.DrvCPEndpoint, fmt.Sprintf("failed to get API Server URL: %v", err), out.V{"profileArg": fmt.Sprintf("--profile=%s", clusterName)})
|
||||
}
|
||||
|
||||
if cc.KubernetesConfig.APIServerName != constants.APIServerName {
|
||||
|
|
|
@ -62,7 +62,7 @@ func init() {
|
|||
Reg = Register{
|
||||
// Expected step orders, organized by the initial step seen
|
||||
steps: map[RegStep][]RegStep{
|
||||
InitialSetup: []RegStep{
|
||||
InitialSetup: {
|
||||
InitialSetup,
|
||||
SelectingDriver,
|
||||
DownloadingArtifacts,
|
||||
|
@ -78,10 +78,10 @@ func init() {
|
|||
Done,
|
||||
},
|
||||
|
||||
Stopping: []RegStep{Stopping, Done},
|
||||
Pausing: []RegStep{Pausing, Done},
|
||||
Unpausing: []RegStep{Unpausing, Done},
|
||||
Deleting: []RegStep{Deleting, Stopping, Deleting, Done},
|
||||
Stopping: {Stopping, Done},
|
||||
Pausing: {Pausing, Done},
|
||||
Unpausing: {Unpausing, Done},
|
||||
Deleting: {Deleting, Stopping, Deleting, Done},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ func TestTimeCommandLogs(t *testing.T) {
|
|||
if !ok {
|
||||
t.Fatalf("expected log %s but didn't find it", log)
|
||||
}
|
||||
if actualTime < time {
|
||||
// Let's give a little wiggle room so we don't fail if time is 3 and actualTime is 2.999
|
||||
if actualTime < time && time-actualTime > 0.001 {
|
||||
t.Fatalf("expected log \"%s\" to take more time than it actually did. got %v, expected > %v", log, actualTime, time)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,12 +202,7 @@ var hostIssues = []match{
|
|||
GOOS: []string{"linux"},
|
||||
},
|
||||
{
|
||||
Kind: Kind{
|
||||
ID: "HOST_HOME_PERMISSION",
|
||||
ExitCode: ExGuestPermission,
|
||||
Advice: "Your user lacks permissions to the minikube profile directory. Run: 'sudo chown -R $USER $HOME/.minikube; chmod -R u+wrx $HOME/.minikube' to fix",
|
||||
Issues: []int{9165},
|
||||
},
|
||||
Kind: HostHomePermission,
|
||||
Regexp: re(`/.minikube/.*: permission denied`),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -188,10 +188,17 @@ var (
|
|||
|
||||
RsrcInsufficientStorage = Kind{ID: "RSRC_INSUFFICIENT_STORAGE", ExitCode: ExInsufficientStorage, Style: style.UnmetRequirement}
|
||||
|
||||
HostHomeMkdir = Kind{ID: "HOST_HOME_MKDIR", ExitCode: ExHostPermission}
|
||||
HostHomeChown = Kind{ID: "HOST_HOME_CHOWN", ExitCode: ExHostPermission}
|
||||
HostBrowser = Kind{ID: "HOST_BROWSER", ExitCode: ExHostError}
|
||||
HostConfigLoad = Kind{ID: "HOST_CONFIG_LOAD", ExitCode: ExHostConfig}
|
||||
HostHomeMkdir = Kind{ID: "HOST_HOME_MKDIR", ExitCode: ExHostPermission}
|
||||
HostHomeChown = Kind{ID: "HOST_HOME_CHOWN", ExitCode: ExHostPermission}
|
||||
HostBrowser = Kind{ID: "HOST_BROWSER", ExitCode: ExHostError}
|
||||
HostConfigLoad = Kind{ID: "HOST_CONFIG_LOAD", ExitCode: ExHostConfig}
|
||||
HostHomePermission = Kind{
|
||||
ID: "HOST_HOME_PERMISSION",
|
||||
ExitCode: ExHostPermission,
|
||||
Advice: "Your user lacks permissions to the minikube profile directory. Run: 'sudo chown -R $USER $HOME/.minikube; chmod -R u+wrx $HOME/.minikube' to fix",
|
||||
Issues: []int{9165},
|
||||
}
|
||||
|
||||
HostCurrentUser = Kind{ID: "HOST_CURRENT_USER", ExitCode: ExHostConfig}
|
||||
HostDelCache = Kind{ID: "HOST_DEL_CACHE", ExitCode: ExHostError}
|
||||
HostKillMountProc = Kind{ID: "HOST_KILL_MOUNT_PROC", ExitCode: ExHostError}
|
||||
|
@ -207,7 +214,13 @@ var (
|
|||
ProviderNotFound = Kind{ID: "PROVIDER_NOT_FOUND", ExitCode: ExProviderNotFound}
|
||||
ProviderUnavailable = Kind{ID: "PROVIDER_UNAVAILABLE", ExitCode: ExProviderNotFound, Style: style.Shrug}
|
||||
|
||||
DrvCPEndpoint = Kind{ID: "DRV_CP_ENDPOINT", ExitCode: ExDriverError}
|
||||
DrvCPEndpoint = Kind{ID: "DRV_CP_ENDPOINT",
|
||||
Advice: `Recreate the cluster by running:
|
||||
minikube delete {{.profileArg}}
|
||||
minikube start {{.profileArg}}`,
|
||||
ExitCode: ExDriverError,
|
||||
Style: style.Failure,
|
||||
}
|
||||
DrvPortForward = Kind{ID: "DRV_PORT_FORWARD", ExitCode: ExDriverError}
|
||||
DrvUnsupportedMulti = Kind{ID: "DRV_UNSUPPORTED_MULTINODE", ExitCode: ExDriverConflict}
|
||||
DrvUnsupportedOS = Kind{ID: "DRV_UNSUPPORTED_OS", ExitCode: ExDriverUnsupported}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/drivers/kic"
|
||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
|
@ -60,6 +61,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
|
|||
}
|
||||
|
||||
return kic.NewDriver(kic.Config{
|
||||
ClusterName: cc.Name,
|
||||
MachineName: driver.MachineName(cc, n),
|
||||
StorePath: localpath.MiniPath(),
|
||||
ImageDigest: cc.KicBaseImage,
|
||||
|
@ -86,34 +88,41 @@ func status() registry.State {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Quickly returns an error code if server is not running
|
||||
cmd := exec.CommandContext(ctx, oci.Docker, "version", "--format", "{{.Server.Os}}-{{.Server.Version}}")
|
||||
o, err := cmd.Output()
|
||||
output := string(o)
|
||||
if strings.Contains(output, "windows-") {
|
||||
return registry.State{Error: oci.ErrWindowsContainers, Installed: true, Healthy: false, Fix: "Change container type to \"linux\" in Docker Desktop settings", Doc: docURL + "#verify-docker-container-type-is-linux"}
|
||||
if err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
err = errors.Wrapf(err, "deadline exceeded running %q", strings.Join(cmd.Args, " "))
|
||||
}
|
||||
|
||||
}
|
||||
if err == nil {
|
||||
glog.Infof("docker version: %s", output)
|
||||
return checkNeedsImprovement()
|
||||
}
|
||||
glog.Warningf("docker version returned error: %v", err)
|
||||
|
||||
glog.Warningf("docker returned error: %v", err)
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
stderr := strings.TrimSpace(string(exitErr.Stderr))
|
||||
newErr := fmt.Errorf(`%q %v: %s`, strings.Join(cmd.Args, " "), exitErr, stderr)
|
||||
|
||||
return suggestFix(stderr, newErr)
|
||||
}
|
||||
|
||||
// Basic timeout
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
glog.Warningf("%q timed out. ", strings.Join(cmd.Args, " "))
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Restart the Docker service", Doc: docURL}
|
||||
}
|
||||
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
stderr := strings.TrimSpace(string(exitErr.Stderr))
|
||||
newErr := fmt.Errorf(`%q %v: %s`, strings.Join(cmd.Args, " "), exitErr, stderr)
|
||||
return suggestFix(stderr, newErr)
|
||||
glog.Infof("docker version: %s", o)
|
||||
if strings.Contains(string(o), "windows-") {
|
||||
return registry.State{Error: oci.ErrWindowsContainers, Installed: true, Healthy: false, Fix: "Change container type to \"linux\" in Docker Desktop settings", Doc: docURL + "#verify-docker-container-type-is-linux"}
|
||||
}
|
||||
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Doc: docURL}
|
||||
si, err := oci.CachedDaemonInfo("docker")
|
||||
if err != nil {
|
||||
// No known fix because we haven't yet seen a failure here
|
||||
return registry.State{Error: errors.Wrap(err, "docker info"), Installed: true, Healthy: false, Doc: docURL}
|
||||
}
|
||||
|
||||
for _, serr := range si.Errors {
|
||||
return suggestFix(serr, fmt.Errorf("docker info error: %s", serr))
|
||||
}
|
||||
|
||||
return checkNeedsImprovement()
|
||||
}
|
||||
|
||||
// checkNeedsImprovement if overlay mod is installed on a system
|
||||
|
@ -121,6 +130,7 @@ func checkNeedsImprovement() registry.State {
|
|||
if runtime.GOOS == "linux" {
|
||||
return checkOverlayMod()
|
||||
}
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
|
@ -128,15 +138,18 @@ func checkNeedsImprovement() registry.State {
|
|||
func checkOverlayMod() registry.State {
|
||||
if _, err := os.Stat("/sys/module/overlay"); err == nil {
|
||||
glog.Info("overlay module found")
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
if _, err := os.Stat("/sys/module/overlay2"); err == nil {
|
||||
glog.Info("overlay2 module found")
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
}
|
||||
|
||||
glog.Warningf("overlay modules were not found")
|
||||
|
||||
return registry.State{NeedsImprovement: true, Installed: true, Healthy: true, Fix: "enable the overlay Linux kernel module using 'modprobe overlay'"}
|
||||
}
|
||||
|
||||
|
@ -150,10 +163,14 @@ func suggestFix(stderr string, err error) registry.State {
|
|||
return registry.State{Error: err, Installed: true, Running: false, Healthy: false, Fix: "Start the Docker service. If Docker is already running, you may need to reset Docker to factory settings with: Settings > Reset.", Doc: "https://github.com/docker/for-win/issues/1825#issuecomment-450501157"}
|
||||
}
|
||||
|
||||
if strings.Contains(stderr, "Cannot connect") || strings.Contains(stderr, "refused") || strings.Contains(stderr, "Is the docker daemon running") || strings.Contains(stderr, "docker daemon is not running") {
|
||||
if dockerNotRunning(stderr) {
|
||||
return registry.State{Error: err, Installed: true, Running: false, Healthy: false, Fix: "Start the Docker service", Doc: docURL}
|
||||
}
|
||||
|
||||
// We don't have good advice, but at least we can provide a good error message
|
||||
return registry.State{Error: err, Installed: true, Running: true, Healthy: false, Doc: docURL}
|
||||
}
|
||||
|
||||
func dockerNotRunning(s string) bool {
|
||||
return strings.Contains(s, "Cannot connect") || strings.Contains(s, "refused") || strings.Contains(s, "Is the docker daemon running") || strings.Contains(s, "docker daemon is not running")
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
|
|||
}
|
||||
|
||||
return kic.NewDriver(kic.Config{
|
||||
ClusterName: cc.Name,
|
||||
MachineName: driver.MachineName(cc, n),
|
||||
StorePath: localpath.MiniPath(),
|
||||
ImageDigest: strings.Split(cc.KicBaseImage, "@")[0], // for podman does not support docker images references with both a tag and digest.
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright 2020 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 monitor
|
||||
|
||||
const (
|
||||
GithubAccessTokenEnvVar = "GITHUB_ACCESS_TOKEN"
|
||||
OkToTestLabel = "ok-to-test"
|
||||
GithubOwner = "kubernetes"
|
||||
GithubRepo = "minikube"
|
||||
BotName = "minikube-pr-bot"
|
||||
)
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2020 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 monitor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// RunMkcmp runs minikube built at the given pr against minikube at master
|
||||
func RunMkcmp(ctx context.Context, pr int) (string, error) {
|
||||
// run 'git pull' so that minikube dir is up to date
|
||||
if _, err := runCmdInMinikube(ctx, []string{"git", "pull", "origin", "master"}); err != nil {
|
||||
return "", errors.Wrap(err, "running git pull")
|
||||
}
|
||||
mkcmpPath := "out/mkcmp"
|
||||
minikubePath := "out/minikube"
|
||||
if _, err := runCmdInMinikube(ctx, []string{"make", mkcmpPath, minikubePath}); err != nil {
|
||||
return "", errors.Wrap(err, "building minikube and mkcmp at head")
|
||||
}
|
||||
return runCmdInMinikube(ctx, []string{mkcmpPath, minikubePath, fmt.Sprintf("pr://%d", pr)})
|
||||
}
|
||||
|
||||
// runCmdInMinikube runs the cmd and return stdout
|
||||
func runCmdInMinikube(ctx context.Context, command []string) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, command[0], command[1:]...)
|
||||
cmd.Dir = minikubeDir()
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
cmd.Stdout = buf
|
||||
|
||||
log.Printf("Running: %v", cmd.Args)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", errors.Wrapf(err, "running %v: %v", cmd.Args, buf.String())
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func minikubeDir() string {
|
||||
return filepath.Join(os.Getenv("HOME"), "minikube")
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Copyright 2020 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 monitor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// Client provides the context and client with necessary auth
|
||||
// for interacting with the Github API
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
*github.Client
|
||||
owner string
|
||||
repo string
|
||||
}
|
||||
|
||||
// NewClient returns a github client with the necessary auth
|
||||
func NewClient(ctx context.Context, owner, repo string) *Client {
|
||||
githubToken := os.Getenv(GithubAccessTokenEnvVar)
|
||||
// Setup the token for github authentication
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: githubToken},
|
||||
)
|
||||
tc := oauth2.NewClient(context.Background(), ts)
|
||||
|
||||
// Return a client instance from github
|
||||
client := github.NewClient(tc)
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
Client: client,
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
// CommentOnPR comments message on the PR
|
||||
func (g *Client) CommentOnPR(pr int, message string) error {
|
||||
comment := &github.IssueComment{
|
||||
Body: &message,
|
||||
}
|
||||
|
||||
log.Printf("Creating comment on PR %d: %s", pr, message)
|
||||
_, _, err := g.Client.Issues.CreateComment(g.ctx, g.owner, g.repo, pr, comment)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating github comment")
|
||||
}
|
||||
log.Printf("Successfully commented on PR %d.", pr)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListOpenPRsWithLabel returns all open PRs with the specified label
|
||||
func (g *Client) ListOpenPRsWithLabel(label string) ([]int, error) {
|
||||
validPrs := []int{}
|
||||
prs, _, err := g.Client.PullRequests.List(g.ctx, g.owner, g.repo, &github.PullRequestListOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "listing pull requests")
|
||||
}
|
||||
for _, pr := range prs {
|
||||
if prContainsLabel(pr.Labels, label) {
|
||||
validPrs = append(validPrs, pr.GetNumber())
|
||||
}
|
||||
}
|
||||
return validPrs, nil
|
||||
}
|
||||
|
||||
func prContainsLabel(labels []*github.Label, label string) bool {
|
||||
for _, l := range labels {
|
||||
if l == nil {
|
||||
continue
|
||||
}
|
||||
if l.GetName() == label {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NewCommitsExist checks if new commits exist since minikube-pr-bot
|
||||
// commented on the PR. If so, return true.
|
||||
func (g *Client) NewCommitsExist(pr int, login string) (bool, error) {
|
||||
lastCommentTime, err := g.timeOfLastComment(pr, login)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "getting time of last comment by %s on pr %d", login, pr)
|
||||
}
|
||||
lastCommitTime, err := g.timeOfLastCommit(pr)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "getting time of last commit on pr %d", pr)
|
||||
}
|
||||
return lastCommentTime.Before(lastCommitTime), nil
|
||||
}
|
||||
|
||||
func (g *Client) timeOfLastCommit(pr int) (time.Time, error) {
|
||||
var commits []*github.RepositoryCommit
|
||||
|
||||
page := 0
|
||||
resultsPerPage := 30
|
||||
for {
|
||||
c, _, err := g.Client.PullRequests.ListCommits(g.ctx, g.owner, g.repo, pr, &github.ListOptions{
|
||||
Page: page,
|
||||
PerPage: resultsPerPage,
|
||||
})
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
commits = append(commits, c...)
|
||||
if len(c) < resultsPerPage {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
|
||||
lastCommitTime := time.Time{}
|
||||
for _, c := range commits {
|
||||
if newCommitTime := c.GetCommit().GetAuthor().GetDate(); newCommitTime.After(lastCommitTime) {
|
||||
lastCommitTime = newCommitTime
|
||||
}
|
||||
}
|
||||
return lastCommitTime, nil
|
||||
}
|
||||
|
||||
func (g *Client) timeOfLastComment(pr int, login string) (time.Time, error) {
|
||||
var comments []*github.IssueComment
|
||||
|
||||
page := 0
|
||||
resultsPerPage := 30
|
||||
for {
|
||||
c, _, err := g.Client.Issues.ListComments(g.ctx, g.owner, g.repo, pr, &github.IssueListCommentsOptions{
|
||||
ListOptions: github.ListOptions{
|
||||
Page: page,
|
||||
PerPage: resultsPerPage,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
comments = append(comments, c...)
|
||||
if len(c) < resultsPerPage {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
|
||||
// go through comments backwards to find the most recent
|
||||
lastCommentTime := time.Time{}
|
||||
|
||||
for _, c := range comments {
|
||||
if u := c.GetUser(); u != nil {
|
||||
if u.GetLogin() == login {
|
||||
if c.GetCreatedAt().After(lastCommentTime) {
|
||||
lastCommentTime = c.GetCreatedAt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastCommentTime, nil
|
||||
}
|
|
@ -24,7 +24,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/docker/go-units"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -47,6 +47,18 @@ func CalculateSizeInMB(humanReadableSize string) (int, error) {
|
|||
return int(size / units.MiB), nil
|
||||
}
|
||||
|
||||
func ConvertMBToBytes(mbSize int) int64 {
|
||||
return int64(mbSize) * units.MiB
|
||||
}
|
||||
|
||||
func ConvertBytesToMB(byteSize int64) int {
|
||||
return int(ConvertUnsignedBytesToMB(uint64(byteSize)))
|
||||
}
|
||||
|
||||
func ConvertUnsignedBytesToMB(byteSize uint64) int64 {
|
||||
return int64(byteSize / units.MiB)
|
||||
}
|
||||
|
||||
// GetBinaryDownloadURL returns a suitable URL for the platform
|
||||
func GetBinaryDownloadURL(version, platform string) string {
|
||||
switch platform {
|
||||
|
|
|
@ -39,11 +39,11 @@ minikube addons SUBCOMMAND [flags]
|
|||
|
||||
## minikube addons configure
|
||||
|
||||
Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list
|
||||
Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list
|
||||
|
||||
### Synopsis
|
||||
|
||||
Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list
|
||||
Configures the addon w/ADDON_NAME within minikube (example: minikube addons configure registry-creds). For a list of available addons use: minikube addons list
|
||||
|
||||
```
|
||||
minikube addons configure ADDON_NAME [flags]
|
||||
|
|
|
@ -11,8 +11,7 @@ Generate command completion for a shell
|
|||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Outputs minikube shell completion for the given shell (bash, zsh or fish)
|
||||
Outputs minikube shell completion for the given shell (bash, zsh or fish)
|
||||
|
||||
This depends on the bash-completion binary. Example installation instructions:
|
||||
OS X:
|
||||
|
|
|
@ -26,7 +26,7 @@ minikube start [flags]
|
|||
--apiserver-names stringArray A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine
|
||||
--apiserver-port int The apiserver listening port (default 8443)
|
||||
--auto-update-drivers If set, automatically updates drivers to the latest version. Defaults to true. (default true)
|
||||
--base-image string The base image to use for docker/podman drivers. Intended for local development. (default "gcr.io/k8s-minikube/kicbase:v0.0.12-snapshot3@sha256:1d687ba53e19dbe5fafe4cc18aa07f269ecc4b7b622f2251b5bf569ddb474e9b")
|
||||
--base-image string The base image to use for docker/podman drivers. Intended for local development. (default "gcr.io/k8s-minikube/kicbase:v0.0.13-snapshot1@sha256:4d43acbd0050148d4bc399931f1b15253b5e73815b63a67b8ab4a5c9e523403f")
|
||||
--cache-images If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none. (default true)
|
||||
--cni string CNI plug-in to use. Valid options: auto, bridge, calico, cilium, flannel, kindnet, or path to a CNI manifest (default: auto)
|
||||
--container-runtime string The container runtime to be used (docker, cri-o, containerd). (default "docker")
|
||||
|
@ -65,7 +65,7 @@ minikube start [flags]
|
|||
--insecure-registry strings Insecure Docker registries to pass to the Docker daemon. The default service CIDR range will automatically be added.
|
||||
--install-addons If set, install addons. Defaults to true. (default true)
|
||||
--interactive Allow user prompts for more information (default true)
|
||||
--iso-url strings Locations to fetch the minikube ISO from. (default [https://storage.googleapis.com/minikube/iso/minikube-v1.13.0.iso,https://github.com/kubernetes/minikube/releases/download/v1.13.0/minikube-v1.13.0.iso,https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.13.0.iso])
|
||||
--iso-url strings Locations to fetch the minikube ISO from. (default [https://storage.googleapis.com/minikube/iso/minikube-v1.13.1.iso,https://github.com/kubernetes/minikube/releases/download/v1.13.1/minikube-v1.13.1.iso,https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.13.1.iso])
|
||||
--keep-context This will keep the existing kubectl context and will create a minikube context.
|
||||
--kubernetes-version string The Kubernetes version that the minikube VM will use (ex: v1.2.3, 'stable' for v1.19.2, 'latest' for v1.19.2). Defaults to 'stable'.
|
||||
--kvm-gpu Enable experimental NVIDIA GPU support in minikube
|
||||
|
|
|
@ -5,7 +5,7 @@ weight: 1
|
|||
date: 2020-07-15
|
||||
---
|
||||
|
||||
If you have a containerized GCP app with a Kubernetes yaml, you can automatically add your credentials to all your deployed pods dynamically with this minikube addon. You just need to have a credentials file, which can be generated with `gcloud auth login`. If you already have a json credentials file you want specify, use the GOOGLE_APPLICATION_CREDENTIALS environment variable.
|
||||
If you have a containerized GCP app with a Kubernetes yaml, you can automatically add your credentials to all your deployed pods dynamically with this minikube addon. You just need to have a credentials file, which can be generated with `gcloud auth application-default login`. If you already have a json credentials file you want specify, use the GOOGLE_APPLICATION_CREDENTIALS environment variable.
|
||||
|
||||
- Start a cluster:
|
||||
```
|
||||
|
|
|
@ -22,6 +22,7 @@ The NO_PROXY variable here is important: Without setting it, minikube may not be
|
|||
|
||||
* **192.168.99.0/24**: Used by the minikube VM. Configurable for some hypervisors via `--host-only-cidr`
|
||||
* **192.168.39.0/24**: Used by the minikube kvm2 driver.
|
||||
* **192.168.49.0/24**: Used by the minikube docker driver's first cluster.
|
||||
* **10.96.0.0/12**: Used by service cluster IP's. Configurable via `--service-cluster-ip-range`
|
||||
|
||||
One important note: If NO_PROXY is required by non-Kubernetes applications, such as Firefox or Chrome, you may want to specifically add the minikube IP to the comma-separated list, as they may not understand IP ranges ([#3827](https://github.com/kubernetes/minikube/issues/3827)).
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"- Docs https://docs.docker.com/docker-for-mac/#resources": "",
|
||||
"- Docs https://docs.docker.com/docker-for-windows/#resources": "",
|
||||
"- Ensure your {{.driver_name}} daemon has access to enough CPU/memory resources.": "",
|
||||
"- Prune unused {{.driver_name}} images, volumes and abandoned containers.": "",
|
||||
"- Prune unused {{.driver_name}} images, volumes, networks and abandoned containers.\n\n\t\t\t\t{{.driver_name}} system prune --volumes": "",
|
||||
"- Restart your {{.driver_name}} service": "",
|
||||
"A VPN or firewall is interfering with HTTP access to the minikube VM. Alternatively, try a different VM driver: https://minikube.sigs.k8s.io/docs/start/": "",
|
||||
"A firewall is blocking Docker the minikube VM from reaching the image repository. You may need to select --image-repository, or use a proxy.": "",
|
||||
|
@ -45,7 +45,7 @@
|
|||
"Basic Commands:": "",
|
||||
"Because you are using a Docker driver on {{.operating_system}}, the terminal needs to be open to run it.": "",
|
||||
"Bind Address: {{.Address}}": "",
|
||||
"Both driver={{.driver}} and vm-driver={{.vmd}} have been set.\n\n Since vm-driver is deprecated, minikube will default to driver={{.driver}}.\n\n If vm-driver is set in the global config, please run \"minikube config unset vm-driver\" to resolve this warning.": "",
|
||||
"Both driver={{.driver}} and vm-driver={{.vmd}} have been set.\n\n Since vm-driver is deprecated, minikube will default to driver={{.driver}}.\n\n If vm-driver is set in the global config, please run \"minikube config unset vm-driver\" to resolve this warning.\n\t\t\t": "",
|
||||
"CNI plug-in to use. Valid options: auto, bridge, calico, cilium, flannel, kindnet, or path to a CNI manifest (default: auto)": "",
|
||||
"Cannot find directory {{.path}} for mount": "",
|
||||
"Cannot use both --output and --format options": "",
|
||||
|
@ -68,7 +68,7 @@
|
|||
"Confirm that you have a working internet connection and that your VM has not run out of resources by using: 'minikube logs'": "",
|
||||
"Confirm that you have supplied the correct value to --hyperv-virtual-switch using the 'Get-VMSwitch' command": "",
|
||||
"Connect to LoadBalancer services": "",
|
||||
"Consider creating a cluster with larger memory size using `minikube start --memory SIZE_MB`": "",
|
||||
"Consider creating a cluster with larger memory size using `minikube start --memory SIZE_MB` ": "",
|
||||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
|
@ -78,6 +78,7 @@
|
|||
"Creating mount {{.name}} ...": "",
|
||||
"Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB) ...": "",
|
||||
"Creating {{.driver_name}} {{.machine_type}} (CPUs={{.number_of_cpus}}, Memory={{.memory_size}}MB, Disk={{.disk_size}}MB) ...": "",
|
||||
"Current context is \"{{.context}}\"": "",
|
||||
"DEPRECATED, use `driver` instead.": "",
|
||||
"DEPRECATED: Replaced by --cni=bridge": "",
|
||||
"Default group id used for the mount": "",
|
||||
|
@ -91,7 +92,7 @@
|
|||
"Deleting node {{.name}} from cluster {{.cluster}}": "",
|
||||
"Disable checking for the availability of hardware virtualization before the vm is started (virtualbox driver only)": "",
|
||||
"Disable dynamic memory in your VM manager, or pass in a larger --memory value": "",
|
||||
"Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list": "",
|
||||
"Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list ": "",
|
||||
"Disables the filesystem mounts provided by the hypervisors": "",
|
||||
"Disk size allocated to the minikube VM (format: \u003cnumber\u003e[\u003cunit\u003e], where unit = b, k, m or g).": "",
|
||||
"Display dashboard URL instead of opening a browser": "",
|
||||
|
@ -102,10 +103,9 @@
|
|||
"Docker Desktop has less than 2 CPUs configured, but Kubernetes requires at least 2 to be available": "",
|
||||
"Docker Desktop is configured for Windows containers, but Linux containers are required for minikube": "",
|
||||
"Docker Desktop only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "",
|
||||
"Docker Desktop only has {{.size}}MiB available, you may encounter application deployment failures.": "",
|
||||
"Docker has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "",
|
||||
"Docker inside the VM is unavailable. Try running 'minikube delete' to reset the VM.": "",
|
||||
"Docker is nearly out of disk space, which may cause deployments to fail! ({{.p}}% of capacity)": "",
|
||||
"Docker is out of disk space! (/var is at {{.p}}% of capacity)": "",
|
||||
"Docs have been saved at - {{.path}}": "",
|
||||
"Documentation: {{.url}}": "",
|
||||
"Done! kubectl is now configured to use \"{{.name}}\" by default": "",
|
||||
|
@ -127,7 +127,7 @@
|
|||
"Enable or disable a minikube addon": "",
|
||||
"Enable proxy for NAT DNS requests (virtualbox driver only)": "",
|
||||
"Enabled addons: {{.addons}}": "",
|
||||
"Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list": "",
|
||||
"Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list ": "",
|
||||
"Enabling '{{.name}}' returned an error: {{.error}}": "",
|
||||
"Enabling dashboard ...": "",
|
||||
"Ensure that CRI-O is installed and healthy: Run 'sudo systemctl start crio' and 'journalctl -u crio'. Alternatively, use --container-runtime=docker": "",
|
||||
|
@ -161,6 +161,7 @@
|
|||
"Error starting cluster": "",
|
||||
"Error starting mount": "",
|
||||
"Error while setting kubectl current context : {{.error}}": "",
|
||||
"Error while setting kubectl current context: {{.error}}": "",
|
||||
"Error writing mount pid": "",
|
||||
"Examples": "",
|
||||
"Executing \"{{.command}}\" took an unusually long time: {{.duration}}": "",
|
||||
|
@ -180,7 +181,6 @@
|
|||
"Failed to delete images": "",
|
||||
"Failed to delete images from config": "",
|
||||
"Failed to enable container runtime": "",
|
||||
"Failed to get API Server URL": "",
|
||||
"Failed to get bootstrapper": "",
|
||||
"Failed to get command runner": "",
|
||||
"Failed to get image map": "",
|
||||
|
@ -208,7 +208,7 @@
|
|||
"Force minikube to perform possibly dangerous operations": "",
|
||||
"Format to print stdout in. Options include: [text,json]": "",
|
||||
"Found network options:": "",
|
||||
"Found {{.number}} invalid profile(s) !": "",
|
||||
"Found {{.number}} invalid profile(s) ! ": "",
|
||||
"Generate command completion for a shell": "",
|
||||
"Generate unable to parse disk size '{{.diskSize}}': {{.error}}": "",
|
||||
"Generate unable to parse memory '{{.memory}}': {{.error}}": "",
|
||||
|
@ -232,7 +232,7 @@
|
|||
"If set, install addons. Defaults to true.": "",
|
||||
"If set, pause all namespaces": "",
|
||||
"If set, unpause all namespaces": "",
|
||||
"If the above advice does not help, please let us know:": "",
|
||||
"If the above advice does not help, please let us know: ": "",
|
||||
"If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none.": "",
|
||||
"If true, only download and cache files for later use - don't install or start anything.": "",
|
||||
"If true, the added node will be marked for work. Defaults to true.": "",
|
||||
|
@ -277,7 +277,7 @@
|
|||
"Mounts the specified directory into minikube.": "",
|
||||
"Multi-node clusters are currently experimental and might exhibit unintended behavior.": "",
|
||||
"Multiple errors deleting profiles": "",
|
||||
"Multiple minikube profiles were found -": "",
|
||||
"Multiple minikube profiles were found - ": "",
|
||||
"NIC Type used for host only network. One of Am79C970A, Am79C973, 82540EM, 82543GC, 82545EM, or virtio (virtualbox driver only)": "",
|
||||
"NIC Type used for nat network. One of Am79C970A, Am79C973, 82540EM, 82543GC, 82545EM, or virtio (virtualbox driver only)": "",
|
||||
"NOTE: This process must stay alive for the mount to be accessible ...": "",
|
||||
|
@ -299,21 +299,21 @@
|
|||
"One of 'yaml' or 'json'.": "",
|
||||
"Only alphanumeric and dashes '-' are permitted. Minimum 1 character, starting with alphanumeric.": "",
|
||||
"Open the addons URL with https instead of http": "",
|
||||
"Open the service URL with https instead of http": "",
|
||||
"Open the service URL with https instead of http (defaults to \\\"false\\\")": "",
|
||||
"Opening Kubernetes service {{.namespace_name}}/{{.service_name}} in default browser...": "",
|
||||
"Opening service {{.namespace_name}}/{{.service_name}} in default browser...": "",
|
||||
"Opening {{.url}} in your default browser...": "",
|
||||
"Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list": "",
|
||||
"Opens the addon w/ADDON_NAME within minikube (example: minikube addons open dashboard). For a list of available addons use: minikube addons list ": "",
|
||||
"Operations on nodes": "",
|
||||
"Options: {{.options}}": "",
|
||||
"Output format. Accepted values: [json]": "",
|
||||
"Outputs minikube shell completion for the given shell (bash, zsh or fish)\n\n\tThis depends on the bash-completion binary. Example installation instructions:\n\tOS X:\n\t\t$ brew install bash-completion\n\t\t$ source $(brew --prefix)/etc/bash_completion\n\t\t$ minikube completion bash \u003e ~/.minikube-completion # for bash users\n\t\t$ minikube completion zsh \u003e ~/.minikube-completion # for zsh users\n\t\t$ source ~/.minikube-completion\n\t\t$ minikube completion fish \u003e ~/.config/fish/completions/minikube.fish # for fish users\n\tUbuntu:\n\t\t$ apt-get install bash-completion\n\t\t$ source /etc/bash-completion\n\t\t$ source \u003c(minikube completion bash) # for bash users\n\t\t$ source \u003c(minikube completion zsh) # for zsh users\n\t\t$ minikube completion fish \u003e ~/.config/fish/completions/minikube.fish # for fish users\n\n\tAdditionally, you may want to output the completion to a file and source in your .bashrc\n\n\tNote for zsh users: [1] zsh completions are only supported in versions of zsh \u003e= 5.2\n\tNote for fish users: [2] please refer to this docs for more details https://fishshell.com/docs/current/#tab-completion": "",
|
||||
"Outputs minikube shell completion for the given shell (bash, zsh or fish)\n\n\tThis depends on the bash-completion binary. Example installation instructions:\n\tOS X:\n\t\t$ brew install bash-completion\n\t\t$ source $(brew --prefix)/etc/bash_completion\n\t\t$ minikube completion bash \u003e ~/.minikube-completion # for bash users\n\t\t$ minikube completion zsh \u003e ~/.minikube-completion # for zsh users\n\t\t$ source ~/.minikube-completion\n\t\t$ minikube completion fish \u003e ~/.config/fish/completions/minikube.fish # for fish users\n\tUbuntu:\n\t\t$ apt-get install bash-completion\n\t\t$ source /etc/bash-completion\n\t\t$ source \u003c(minikube completion bash) # for bash users\n\t\t$ source \u003c(minikube completion zsh) # for zsh users\n\t\t$ minikube completion fish \u003e ~/.config/fish/completions/minikube.fish # for fish users\n\n\tAdditionally, you may want to output the completion to a file and source in your .bashrc\n\n\tNote for zsh users: [1] zsh completions are only supported in versions of zsh \u003e= 5.2\n\tNote for fish users: [2] please refer to this docs for more details https://fishshell.com/docs/current/#tab-completion\n": "",
|
||||
"Pause": "",
|
||||
"Paused {{.count}} containers": "",
|
||||
"Paused {{.count}} containers in: {{.namespaces}}": "",
|
||||
"Pausing node {{.name}} ...": "",
|
||||
"Pausing node {{.name}} ... ": "",
|
||||
"Permissions: {{.octalMode}} ({{.writtenMode}})": "",
|
||||
"Please create a cluster with bigger disk size: `minikube start --disk SIZE_MB`": "",
|
||||
"Please create a cluster with bigger disk size: `minikube start --disk SIZE_MB` ": "",
|
||||
"Please either authenticate to the registry or use --base-image flag to use a different registry.": "",
|
||||
"Please enter a value:": "",
|
||||
"Please free up disk or prune images.": "",
|
||||
|
@ -321,11 +321,11 @@
|
|||
"Please install the minikube hyperkit VM driver, or select an alternative --driver": "",
|
||||
"Please install the minikube kvm2 VM driver, or select an alternative --driver": "",
|
||||
"Please make sure the service you are looking for is deployed or is in the correct namespace.": "",
|
||||
"Please re-eval your docker-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} docker-env'": "",
|
||||
"Please re-eval your podman-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} podman-env'": "",
|
||||
"Please re-eval your docker-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} docker-env'\n\n\t": "",
|
||||
"Please re-eval your podman-env, To ensure your environment variables have updated ports:\n\n\t'minikube -p {{.profile_name}} podman-env'\n\n\t": "",
|
||||
"Please see {{.documentation_url}} for more details": "",
|
||||
"Please specify the directory to be mounted: \n\tminikube mount \u003csource directory\u003e:\u003ctarget directory\u003e (example: \"/host-home:/vm-home\")": "",
|
||||
"Please visit the following link for documentation around this: \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages": "",
|
||||
"Please visit the following link for documentation around this: \n\thttps://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages\n": "",
|
||||
"Populates the specified folder with documentation in markdown about minikube": "",
|
||||
"PowerShell is running in constrained mode, which is incompatible with Hyper-V scripting.": "",
|
||||
"Powering off \"{{.profile_name}}\" via SSH ...": "",
|
||||
|
@ -400,7 +400,7 @@
|
|||
"Show only log entries which point to known problems": "",
|
||||
"Show only the most recent journal entries, and continuously print new entries as they are appended to the journal.": "",
|
||||
"Skipped switching kubectl context for {{.profile_name}} because --keep-context was set.": "",
|
||||
"Some dashboard features require the metrics-server addon. To enable all features please run:\n\n\tminikube{{.profileArg}} addons enable metrics-server": "",
|
||||
"Some dashboard features require the metrics-server addon. To enable all features please run:\n\n\tminikube{{.profileArg}} addons enable metrics-server\t\n\n": "",
|
||||
"Sorry, Kubernetes {{.k8sVersion}} requires conntrack to be installed in root's path": "",
|
||||
"Sorry, completion support is not yet implemented for {{.name}}": "",
|
||||
"Sorry, please set the --output flag to one of the following valid options: [text,json]": "",
|
||||
|
@ -555,12 +555,12 @@
|
|||
"Unable to safely downgrade existing Kubernetes v{{.old}} cluster to v{{.new}}": "",
|
||||
"Unable to stop VM": "",
|
||||
"Unable to update {{.driver}} driver: {{.error}}": "",
|
||||
"Unfortunately, could not download the base image {{.image_name}}": "",
|
||||
"Unfortunately, could not download the base image {{.image_name}} ": "",
|
||||
"Uninstalling Kubernetes {{.kubernetes_version}} using {{.bootstrapper_name}} ...": "",
|
||||
"Unmounting {{.path}} ...": "",
|
||||
"Unpaused {{.count}} containers": "",
|
||||
"Unpaused {{.count}} containers in: {{.namespaces}}": "",
|
||||
"Unpausing node {{.name}} ...": "",
|
||||
"Unpausing node {{.name}} ... ": "",
|
||||
"Unset the KUBECONFIG environment variable, or verify that it does not point to an empty or otherwise invalid path": "",
|
||||
"Unset variables instead of setting them": "",
|
||||
"Update kubeconfig in case of an IP or port change": "",
|
||||
|
@ -583,7 +583,7 @@
|
|||
"Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.": "",
|
||||
"User ID: {{.userID}}": "",
|
||||
"Userspace file server is shutdown": "",
|
||||
"Userspace file server:": "",
|
||||
"Userspace file server: ": "",
|
||||
"Using image repository {{.name}}": "",
|
||||
"Using podman 2 is not supported yet. your version is \"{{.currentVersion}}\". minikube might not work. use at your own risk.": "",
|
||||
"Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "",
|
||||
|
@ -608,7 +608,7 @@
|
|||
"Where to root the NFS Shares, defaults to /nfsshares (hyperkit driver only)": "",
|
||||
"Whether to use external switch over Default Switch if virtual switch not explicitly specified. (hyperv driver only)": "",
|
||||
"You appear to be using a proxy, but your NO_PROXY environment does not include the minikube IP ({{.ip_address}}).": "",
|
||||
"You can delete them using the following command(s):": "",
|
||||
"You can delete them using the following command(s): ": "",
|
||||
"You can force an unsupported Kubernetes version via the --force flag": "",
|
||||
"You cannot change the CPUs for an existing minikube cluster. Please first delete the cluster.": "",
|
||||
"You cannot change the Disk size for an exiting minikube cluster. Please first delete the cluster.": "",
|
||||
|
@ -622,13 +622,13 @@
|
|||
"Your host is failing to route packets to the minikube VM. If you have VPN software, try turning it off or configuring it so that it does not re-route traffic to the VM IP. If not, check your VM environment routing options.": "",
|
||||
"Your minikube config refers to an unsupported driver. Erase ~/.minikube, and try again.": "",
|
||||
"Your minikube vm is not running, try minikube start.": "",
|
||||
"Your user lacks permissions to the minikube profile directory. Run: 'sudo chown -R $USER $HOME/.minikube; chmod -R u+wrx $HOME/.minikube' to fix": "",
|
||||
"[WARNING] For full functionality, the 'csi-hostpath-driver' addon requires the 'volumesnapshots' addon to be enabled.\n\nYou can enable 'volumesnapshots' addon by running: 'minikube addons enable volumesnapshots'\n": "",
|
||||
"addon '{{.name}}' is currently not enabled.\nTo enable this addon run:\nminikube addons enable {{.name}}": "",
|
||||
"addon '{{.name}}' is not a valid addon packaged with minikube.\nTo see the list of available addons run:\nminikube addons list": "",
|
||||
"addons modifies minikube addons files using subcommands like \"minikube addons enable dashboard\"": "",
|
||||
"bash completion failed": "",
|
||||
"call with cleanup=true to remove old tunnels": "",
|
||||
"config modifies minikube config files using subcommands like \"minikube config set driver kvm\"\nConfigurable fields:\\n\\n": "",
|
||||
"config modifies minikube config files using subcommands like \"minikube config set driver kvm\"\nConfigurable fields: \\n\\n": "",
|
||||
"config view failed": "",
|
||||
"dashboard service is not running: {{.error}}": "",
|
||||
"deleting node": "",
|
||||
|
@ -660,14 +660,14 @@
|
|||
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "",
|
||||
"kubectl proxy": "",
|
||||
"libmachine failed": "",
|
||||
"list displays all valid default settings for PROPERTY_NAME\nAcceptable fields:\\n\\n": "",
|
||||
"list displays all valid default settings for PROPERTY_NAME\nAcceptable fields: \\n\\n": "",
|
||||
"logdir set failed": "",
|
||||
"max time to wait per Kubernetes or host to be healthy.": "",
|
||||
"minikube addons list --output OUTPUT. json, list": "",
|
||||
"minikube is exiting due to an error. If the above message is not useful, open an issue:": "",
|
||||
"minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "",
|
||||
"minikube is unable to access the Google Container Registry. You may need to configure it to use a HTTP proxy.": "",
|
||||
"minikube is unable to connect to the VM: {{.error}}\n\n\tThis is likely due to one of two reasons:\n\n\t- VPN or firewall interference\n\t- {{.hypervisor}} network configuration issue\n\n\tSuggested workarounds:\n\n\t- Disable your local VPN or firewall software\n\t- Configure your local VPN or firewall to allow access to {{.ip}}\n\t- Restart or reinstall {{.hypervisor}}\n\t- Use an alternative --vm-driver\n\t- Use --force to override this connectivity check": "",
|
||||
"minikube is unable to connect to the VM: {{.error}}\n\n\tThis is likely due to one of two reasons:\n\n\t- VPN or firewall interference\n\t- {{.hypervisor}} network configuration issue\n\n\tSuggested workarounds:\n\n\t- Disable your local VPN or firewall software\n\t- Configure your local VPN or firewall to allow access to {{.ip}}\n\t- Restart or reinstall {{.hypervisor}}\n\t- Use an alternative --vm-driver\n\t- Use --force to override this connectivity check\n\t": "",
|
||||
"minikube profile was successfully set to {{.profile_name}}": "",
|
||||
"minikube provisions and manages local Kubernetes clusters optimized for development workflows.": "",
|
||||
"minikube quickly sets up a local Kubernetes cluster": "",
|
||||
|
@ -715,6 +715,7 @@
|
|||
"version yaml failure": "",
|
||||
"zsh completion failed": "",
|
||||
"{{ .name }}: {{ .rejection }}": "",
|
||||
"{{.Driver}} is currently using the {{.StorageDriver}} storage driver, consider switching to overlay2 for better performance": "",
|
||||
"{{.count}} nodes stopped.": "",
|
||||
"{{.driver_name}} \"{{.cluster}}\" {{.machine_type}} is missing, will recreate.": "",
|
||||
"{{.driver_name}} couldn't proceed because {{.driver_name}} service is not healthy.": "",
|
||||
|
@ -725,6 +726,8 @@
|
|||
"{{.name}} has no available configuration options": "",
|
||||
"{{.name}} is already running": "",
|
||||
"{{.name}} was successfully configured": "",
|
||||
"{{.n}} is nearly out of disk space, which may cause deployments to fail! ({{.p}}% of capacity)": "",
|
||||
"{{.n}} is out of disk space! (/var is at {{.p}}% of capacity)": "",
|
||||
"{{.ocibin}} is taking an unsually long time to respond, consider restarting {{.ocibin}}": "",
|
||||
"{{.path}} is version {{.client_version}}, which may have incompatibilites with Kubernetes {{.cluster_version}}.": "",
|
||||
"{{.prefix}}minikube {{.version}} on {{.platform}}": "",
|
||||
|
|
Loading…
Reference in New Issue