Merge branch 'master' of github.com:kubernetes/minikube into 1.5.0-beta.0
commit
30f9577954
|
@ -3,7 +3,7 @@
|
|||
os: linux
|
||||
language: go
|
||||
go:
|
||||
- 1.12.9
|
||||
- 1.12.12
|
||||
env:
|
||||
global:
|
||||
- GOPROXY=https://proxy.golang.org
|
||||
|
@ -19,7 +19,7 @@ matrix:
|
|||
|
||||
- language: go
|
||||
name: Code Lint
|
||||
go: 1.12.9
|
||||
go: 1.12.12
|
||||
env:
|
||||
- TESTSUITE=lint
|
||||
before_install:
|
||||
|
@ -28,7 +28,7 @@ matrix:
|
|||
|
||||
- language: go
|
||||
name: Unit Test
|
||||
go: 1.12.9
|
||||
go: 1.12.12
|
||||
env:
|
||||
- TESTSUITE=unittest
|
||||
before_install:
|
||||
|
|
82
Makefile
82
Makefile
|
@ -26,7 +26,7 @@ DEB_VERSION ?= $(subst -,~,$(RAW_VERSION))
|
|||
RPM_VERSION ?= $(DEB_VERSION)
|
||||
|
||||
# used by hack/jenkins/release_build_and_upload.sh and KVM_BUILD_IMAGE, see also BUILD_IMAGE below
|
||||
GO_VERSION ?= 1.12.9
|
||||
GO_VERSION ?= 1.12.12
|
||||
|
||||
INSTALL_SIZE ?= $(shell du out/minikube-windows-amd64.exe | cut -f1)
|
||||
BUILDROOT_BRANCH ?= 2019.02.6
|
||||
|
@ -127,17 +127,30 @@ endif
|
|||
|
||||
ifeq ($(GOOS),windows)
|
||||
IS_EXE = .exe
|
||||
DIRSEP_ = \\
|
||||
DIRSEP = $(strip $(DIRSEP_))
|
||||
PATHSEP = ;
|
||||
else
|
||||
DIRSEP = /
|
||||
PATHSEP = :
|
||||
endif
|
||||
|
||||
|
||||
out/minikube-linux-x86_64: out/minikube-linux-amd64
|
||||
cp $< $@
|
||||
|
||||
out/minikube-linux-aarch64: out/minikube-linux-arm64
|
||||
cp $< $@
|
||||
|
||||
out/minikube$(IS_EXE): out/minikube-$(GOOS)-$(GOARCH)$(IS_EXE)
|
||||
cp $< $@
|
||||
|
||||
out/minikube-windows-amd64.exe: out/minikube-windows-amd64
|
||||
cp $< $@
|
||||
|
||||
.PHONY: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe
|
||||
.PHONY: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe
|
||||
minikube-linux-amd64: out/minikube-linux-amd64
|
||||
minikube-linux-arm64: out/minikube-linux-arm64
|
||||
minikube-darwin-amd64: out/minikube-darwin-amd64
|
||||
minikube-windows-amd64.exe: out/minikube-windows-amd64.exe
|
||||
|
||||
|
@ -239,33 +252,25 @@ extract:
|
|||
pkg/minikube/assets/assets.go: $(shell find "deploy/addons" -type f)
|
||||
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
|
||||
else ifeq ($(GOOS),windows)
|
||||
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
|
||||
-gofmt -s -w $@
|
||||
else
|
||||
which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
|
||||
-gofmt -s -w $@
|
||||
endif
|
||||
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg assets deploy/addons/...
|
||||
-gofmt -s -w $@
|
||||
@#golint: Dns should be DNS (compat sed)
|
||||
@sed -i -e 's/Dns/DNS/g' $@ && rm -f ./-e
|
||||
|
||||
pkg/minikube/translate/translations.go: $(shell find "translations/" -type f)
|
||||
ifeq ($(MINIKUBE_BUILD_IN_DOCKER),y)
|
||||
$(call DOCKER,$(BUILD_IMAGE),/usr/bin/make $@)
|
||||
else ifeq ($(GOOS),windows)
|
||||
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)\bin" go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH);$(GOPATH)\bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
|
||||
-gofmt -s -w $@
|
||||
else
|
||||
which go-bindata || GO111MODULE=off GOBIN=$(GOPATH)/bin go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH):$(GOPATH)/bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
|
||||
-gofmt -s -w $@
|
||||
endif
|
||||
which go-bindata || GO111MODULE=off GOBIN="$(GOPATH)$(DIRSEP)bin" go get github.com/jteeuwen/go-bindata/...
|
||||
PATH="$(PATH)$(PATHSEP)$(GOPATH)$(DIRSEP)bin" go-bindata -nomemcopy -o $@ -pkg translate translations/...
|
||||
-gofmt -s -w $@
|
||||
@#golint: Json should be JSON (compat sed)
|
||||
@sed -i -e 's/Json/JSON/' $@ && rm -f ./-e
|
||||
|
||||
.PHONY: cross
|
||||
cross: minikube-linux-amd64 minikube-darwin-amd64 minikube-windows-amd64.exe
|
||||
cross: minikube-linux-amd64 minikube-linux-arm64 minikube-darwin-amd64 minikube-windows-amd64.exe
|
||||
|
||||
.PHONY: windows
|
||||
windows: minikube-windows-amd64.exe
|
||||
|
@ -281,7 +286,8 @@ e2e-cross: e2e-linux-amd64 e2e-darwin-amd64 e2e-windows-amd64.exe
|
|||
|
||||
.PHONY: checksum
|
||||
checksum:
|
||||
for f in out/minikube-linux-amd64 out/minikube-darwin-amd64 out/minikube-windows-amd64.exe out/minikube.iso \
|
||||
for f in out/minikube.iso out/minikube-linux-amd64 minikube-linux-arm64 \
|
||||
out/minikube-darwin-amd64 out/minikube-windows-amd64.exe \
|
||||
out/docker-machine-driver-kvm2 out/docker-machine-driver-hyperkit; do \
|
||||
if [ -f "$${f}" ]; then \
|
||||
openssl sha256 "$${f}" | awk '{print $$2}' > "$${f}.sha256" ; \
|
||||
|
@ -312,7 +318,7 @@ vet:
|
|||
@go vet $(SOURCE_PACKAGES)
|
||||
|
||||
.PHONY: golint
|
||||
golint:
|
||||
golint: pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go
|
||||
@golint -set_exit_status $(SOURCE_PACKAGES)
|
||||
|
||||
.PHONY: gocyclo
|
||||
|
@ -348,21 +354,29 @@ mdlint:
|
|||
out/docs/minikube.md: $(shell find "cmd") $(shell find "pkg/minikube/constants") pkg/minikube/assets/assets.go pkg/minikube/translate/translations.go
|
||||
go run -ldflags="$(MINIKUBE_LDFLAGS)" -tags gendocs hack/help_text/gen_help_text.go
|
||||
|
||||
out/minikube_$(DEB_VERSION).deb: out/minikube-linux-amd64
|
||||
out/minikube_$(DEB_VERSION).deb: out/minikube_$(DEB_VERSION)-0_amd64.deb
|
||||
cp $< $@
|
||||
|
||||
out/minikube_$(DEB_VERSION)-0_%.deb: out/minikube-linux-%
|
||||
cp -r installers/linux/deb/minikube_deb_template out/minikube_$(DEB_VERSION)
|
||||
chmod 0755 out/minikube_$(DEB_VERSION)/DEBIAN
|
||||
sed -E -i 's/--VERSION--/'$(DEB_VERSION)'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control
|
||||
sed -E -i 's/--ARCH--/'$*'/g' out/minikube_$(DEB_VERSION)/DEBIAN/control
|
||||
mkdir -p out/minikube_$(DEB_VERSION)/usr/bin
|
||||
cp out/minikube-linux-amd64 out/minikube_$(DEB_VERSION)/usr/bin/minikube
|
||||
fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION)
|
||||
cp $< out/minikube_$(DEB_VERSION)/usr/bin/minikube
|
||||
fakeroot dpkg-deb --build out/minikube_$(DEB_VERSION) $@
|
||||
rm -rf out/minikube_$(DEB_VERSION)
|
||||
|
||||
out/minikube-$(RPM_VERSION).rpm: out/minikube-linux-amd64
|
||||
out/minikube-$(RPM_VERSION).rpm: out/minikube-$(RPM_VERSION)-0.x86_64.rpm
|
||||
cp $< $@
|
||||
|
||||
out/minikube-$(RPM_VERSION)-0.%.rpm: out/minikube-linux-%
|
||||
cp -r installers/linux/rpm/minikube_rpm_template out/minikube-$(RPM_VERSION)
|
||||
sed -E -i 's/--VERSION--/'$(RPM_VERSION)'/g' out/minikube-$(RPM_VERSION)/minikube.spec
|
||||
sed -E -i 's|--OUT--|'$(PWD)/out'|g' out/minikube-$(RPM_VERSION)/minikube.spec
|
||||
rpmbuild -bb -D "_rpmdir $(PWD)/out" -D "_rpmfilename minikube-$(RPM_VERSION).rpm" \
|
||||
rpmbuild -bb -D "_rpmdir $(PWD)/out" --target $* \
|
||||
out/minikube-$(RPM_VERSION)/minikube.spec
|
||||
@mv out/$*/minikube-$(RPM_VERSION)-0.$*.rpm out/ && rmdir out/$*
|
||||
rm -rf out/minikube-$(RPM_VERSION)
|
||||
|
||||
.PHONY: apt
|
||||
|
@ -380,14 +394,16 @@ out/repodata/repomd.xml: out/minikube-$(RPM_VERSION).rpm
|
|||
-u "$(MINIKUBE_RELEASES_URL)/$(VERSION)/" out
|
||||
|
||||
.SECONDEXPANSION:
|
||||
TAR_TARGETS_linux := out/minikube-linux-amd64 out/docker-machine-driver-kvm2
|
||||
TAR_TARGETS_darwin := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit
|
||||
TAR_TARGETS_windows := out/minikube-windows-amd64.exe
|
||||
out/minikube-%-amd64.tar.gz: $$(TAR_TARGETS_$$*)
|
||||
TAR_TARGETS_linux-amd64 := out/minikube-linux-amd64 out/docker-machine-driver-kvm2
|
||||
TAR_TARGETS_linux-arm64 := out/minikube-linux-arm64
|
||||
TAR_TARGETS_darwin-amd64 := out/minikube-darwin-amd64 out/docker-machine-driver-hyperkit
|
||||
TAR_TARGETS_windows-amd64 := out/minikube-windows-amd64.exe
|
||||
out/minikube-%.tar.gz: $$(TAR_TARGETS_$$*)
|
||||
tar -cvzf $@ $^
|
||||
|
||||
.PHONY: cross-tars
|
||||
cross-tars: out/minikube-windows-amd64.tar.gz out/minikube-linux-amd64.tar.gz out/minikube-darwin-amd64.tar.gz
|
||||
cross-tars: out/minikube-linux-amd64.tar.gz out/minikube-linux-arm64.tar.gz \
|
||||
out/minikube-windows-amd64.tar.gz out/minikube-darwin-amd64.tar.gz
|
||||
-cd out && $(SHA512SUM) *.tar.gz > SHA512SUM
|
||||
|
||||
out/minikube-installer.exe: out/minikube-windows-amd64.exe
|
||||
|
@ -551,3 +567,7 @@ site: site/themes/docsy/assets/vendor/bootstrap/package.js out/hugo/hugo
|
|||
--navigateToChanged \
|
||||
--ignoreCache \
|
||||
--buildFuture)
|
||||
|
||||
.PHONY: out/mkcmp
|
||||
out/mkcmp:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ cmd/performance/main.go
|
||||
|
|
|
@ -17,18 +17,23 @@ limitations under the License.
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
)
|
||||
|
||||
const defaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n"
|
||||
|
||||
var addonListFormat string
|
||||
var addonListOutput string
|
||||
|
||||
// AddonListTemplate represents the addon list template
|
||||
type AddonListTemplate struct {
|
||||
|
@ -44,9 +49,18 @@ var addonsListCmd = &cobra.Command{
|
|||
if len(args) != 0 {
|
||||
exit.UsageT("usage: minikube addons list")
|
||||
}
|
||||
err := addonList()
|
||||
if err != nil {
|
||||
exit.WithError("addon list failed", err)
|
||||
|
||||
if addonListOutput != "list" && addonListFormat != defaultAddonListFormat {
|
||||
exit.UsageT("Cannot use both --output and --format options")
|
||||
}
|
||||
|
||||
switch strings.ToLower(addonListOutput) {
|
||||
case "list":
|
||||
printAddonsList()
|
||||
case "json":
|
||||
printAddonsJSON()
|
||||
default:
|
||||
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'list', 'json'", addonListOutput))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -59,17 +73,25 @@ func init() {
|
|||
defaultAddonListFormat,
|
||||
`Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
|
||||
For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`)
|
||||
|
||||
addonsListCmd.Flags().StringVarP(
|
||||
&addonListOutput,
|
||||
"output",
|
||||
"o",
|
||||
"list",
|
||||
`minikube addons list --output OUTPUT. json, list`)
|
||||
|
||||
AddonsCmd.AddCommand(addonsListCmd)
|
||||
}
|
||||
|
||||
func stringFromStatus(addonStatus bool) string {
|
||||
var stringFromStatus = func(addonStatus bool) string {
|
||||
if addonStatus {
|
||||
return "enabled"
|
||||
}
|
||||
return "disabled"
|
||||
}
|
||||
|
||||
func addonList() error {
|
||||
var printAddonsList = func() {
|
||||
addonNames := make([]string, 0, len(assets.Addons))
|
||||
for addonName := range assets.Addons {
|
||||
addonNames = append(addonNames, addonName)
|
||||
|
@ -80,7 +102,7 @@ func addonList() error {
|
|||
addonBundle := assets.Addons[addonName]
|
||||
addonStatus, err := addonBundle.IsEnabled()
|
||||
if err != nil {
|
||||
return err
|
||||
exit.WithError("Error getting addons status", err)
|
||||
}
|
||||
tmpl, err := template.New("list").Parse(addonListFormat)
|
||||
if err != nil {
|
||||
|
@ -92,5 +114,30 @@ func addonList() error {
|
|||
exit.WithError("Error executing list template", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var printAddonsJSON = func() {
|
||||
addonNames := make([]string, 0, len(assets.Addons))
|
||||
for addonName := range assets.Addons {
|
||||
addonNames = append(addonNames, addonName)
|
||||
}
|
||||
sort.Strings(addonNames)
|
||||
|
||||
addonsMap := map[string]map[string]interface{}{}
|
||||
|
||||
for _, addonName := range addonNames {
|
||||
addonBundle := assets.Addons[addonName]
|
||||
|
||||
addonStatus, err := addonBundle.IsEnabled()
|
||||
if err != nil {
|
||||
exit.WithError("Error getting addons status", err)
|
||||
}
|
||||
|
||||
addonsMap[addonName] = map[string]interface{}{
|
||||
"Status": stringFromStatus(addonStatus),
|
||||
}
|
||||
}
|
||||
jsonString, _ := json.Marshal(addonsMap)
|
||||
|
||||
out.String(string(jsonString))
|
||||
}
|
||||
|
|
|
@ -45,6 +45,15 @@ var ProfileCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
profile := args[0]
|
||||
/**
|
||||
we need to add code over here to check whether the profile
|
||||
name is in the list of reserved keywords
|
||||
*/
|
||||
if pkgConfig.ProfileNameInReservedKeywords(profile) {
|
||||
out.ErrT(out.FailureType, `Profile name "{{.profilename}}" is minikube keyword. To delete profile use command minikube delete -p <profile name> `, out.V{"profilename": profile})
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if profile == "default" {
|
||||
profile = "minikube"
|
||||
} else {
|
||||
|
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
|
@ -29,12 +31,30 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
output string
|
||||
)
|
||||
|
||||
var profileListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "Lists all minikube profiles.",
|
||||
Long: "Lists all valid minikube profiles and detects all possible invalid profiles.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
switch strings.ToLower(output) {
|
||||
case "json":
|
||||
printProfilesJSON()
|
||||
case "table":
|
||||
printProfilesTable()
|
||||
default:
|
||||
exit.WithCodeT(exit.BadUsage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", output))
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
var printProfilesTable = func() {
|
||||
|
||||
var validData [][]string
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
|
@ -65,12 +85,47 @@ var profileListCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Config, fmt.Sprintf("error loading profiles: %v", err))
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
var printProfilesJSON = func() {
|
||||
validProfiles, invalidProfiles, err := config.ListProfiles()
|
||||
|
||||
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{}
|
||||
}
|
||||
|
||||
var body = map[string]interface{}{}
|
||||
|
||||
if err == nil {
|
||||
body["valid"] = valid
|
||||
body["invalid"] = invalid
|
||||
jsonString, _ := json.Marshal(body)
|
||||
out.String(string(jsonString))
|
||||
} else {
|
||||
body["error"] = err
|
||||
jsonString, _ := json.Marshal(body)
|
||||
out.String(string(jsonString))
|
||||
os.Exit(exit.Failure)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
profileListCmd.Flags().StringVarP(&output, "output", "o", "table", "The output format. One of 'json', 'table'")
|
||||
ProfileCmd.AddCommand(profileListCmd)
|
||||
}
|
||||
|
|
|
@ -151,5 +151,5 @@ func posString(slice []string, element string) int {
|
|||
|
||||
// containsString returns true if slice contains element
|
||||
func containsString(slice []string, element string) bool {
|
||||
return !(posString(slice, element) == -1)
|
||||
return posString(slice, element) != -1
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
|
||||
"github.com/docker/machine/libmachine/mcnerror"
|
||||
"github.com/golang/glog"
|
||||
ps "github.com/mitchellh/go-ps"
|
||||
"github.com/mitchellh/go-ps"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
|
@ -43,6 +43,7 @@ import (
|
|||
)
|
||||
|
||||
var deleteAll bool
|
||||
var purge bool
|
||||
|
||||
// deleteCmd represents the delete command
|
||||
var deleteCmd = &cobra.Command{
|
||||
|
@ -56,11 +57,15 @@ associated files.`,
|
|||
type typeOfError int
|
||||
|
||||
const (
|
||||
// Fatal is a type of DeletionError
|
||||
Fatal typeOfError = 0
|
||||
// MissingProfile is a type of DeletionError
|
||||
MissingProfile typeOfError = 1
|
||||
// MissingCluster is a type of DeletionError
|
||||
MissingCluster typeOfError = 2
|
||||
)
|
||||
|
||||
// DeletionError can be returned from DeleteProfiles
|
||||
type DeletionError struct {
|
||||
Err error
|
||||
Errtype typeOfError
|
||||
|
@ -70,6 +75,16 @@ func (error DeletionError) Error() string {
|
|||
return error.Err.Error()
|
||||
}
|
||||
|
||||
func init() {
|
||||
deleteCmd.Flags().BoolVar(&deleteAll, "all", false, "Set flag to delete all profiles")
|
||||
deleteCmd.Flags().BoolVar(&purge, "purge", false, "Set this flag to delete the '.minikube' folder from your user directory.")
|
||||
|
||||
if err := viper.BindPFlags(deleteCmd.Flags()); err != nil {
|
||||
exit.WithError("unable to bind flags", err)
|
||||
}
|
||||
RootCmd.AddCommand(deleteCmd)
|
||||
}
|
||||
|
||||
// runDelete handles the executes the flow of "minikube delete"
|
||||
func runDelete(cmd *cobra.Command, args []string) {
|
||||
if len(args) > 0 {
|
||||
|
@ -80,14 +95,23 @@ func runDelete(cmd *cobra.Command, args []string) {
|
|||
exit.WithError("Could not get profile flag", err)
|
||||
}
|
||||
|
||||
validProfiles, invalidProfiles, err := pkg_config.ListProfiles()
|
||||
profilesToDelete := append(validProfiles, invalidProfiles...)
|
||||
|
||||
// If the purge flag is set, go ahead and delete the .minikube directory.
|
||||
if purge && len(profilesToDelete) > 1 && !deleteAll {
|
||||
out.ErrT(out.Notice, "Multiple minikube profiles were found - ")
|
||||
for _, p := range profilesToDelete {
|
||||
out.T(out.Notice, " - {{.profile}}", out.V{"profile": p.Name})
|
||||
}
|
||||
exit.UsageT("Usage: minikube delete --all --purge")
|
||||
}
|
||||
|
||||
if deleteAll {
|
||||
if profileFlag != constants.DefaultMachineName {
|
||||
exit.UsageT("usage: minikube delete --all")
|
||||
}
|
||||
|
||||
validProfiles, invalidProfiles, err := pkg_config.ListProfiles()
|
||||
profilesToDelete := append(validProfiles, invalidProfiles...)
|
||||
|
||||
if err != nil {
|
||||
exit.WithError("Error getting profiles to delete", err)
|
||||
}
|
||||
|
@ -116,9 +140,18 @@ func runDelete(cmd *cobra.Command, args []string) {
|
|||
out.T(out.DeletingHost, "Successfully deleted profile \"{{.name}}\"", out.V{"name": profileName})
|
||||
}
|
||||
}
|
||||
|
||||
// If the purge flag is set, go ahead and delete the .minikube directory.
|
||||
if purge {
|
||||
glog.Infof("Purging the '.minikube' directory located at %s", localpath.MiniPath())
|
||||
if err := os.RemoveAll(localpath.MiniPath()); err != nil {
|
||||
exit.WithError("unable to delete minikube config folder", err)
|
||||
}
|
||||
out.T(out.Crushed, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory": localpath.MiniPath()})
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes one or more profiles
|
||||
// DeleteProfiles deletes one or more profiles
|
||||
func DeleteProfiles(profiles []*pkg_config.Profile) []error {
|
||||
var errs []error
|
||||
for _, profile := range profiles {
|
||||
|
@ -177,7 +210,7 @@ func deleteProfile(profile *pkg_config.Profile) error {
|
|||
if err = cluster.DeleteHost(api); err != nil {
|
||||
switch errors.Cause(err).(type) {
|
||||
case mcnerror.ErrHostDoesNotExist:
|
||||
out.T(out.Meh, `"{{.name}}" cluster does not exist. Proceeding ahead with cleanup.`, out.V{"name": profile})
|
||||
out.T(out.Meh, `"{{.name}}" cluster does not exist. Proceeding ahead with cleanup.`, out.V{"name": profile.Name})
|
||||
default:
|
||||
out.T(out.FailureType, "Failed to delete cluster: {{.error}}", out.V{"error": err})
|
||||
out.T(out.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, out.V{"name": profile.Name})
|
||||
|
@ -246,7 +279,7 @@ func uninstallKubernetes(api libmachine.API, kc pkg_config.KubernetesConfig, bsN
|
|||
return nil
|
||||
}
|
||||
|
||||
// Handles deletion error from DeleteProfiles
|
||||
// HandleDeletionErrors handles deletion errors from DeleteProfiles
|
||||
func HandleDeletionErrors(errors []error) {
|
||||
if len(errors) == 1 {
|
||||
handleSingleDeletionError(errors[0])
|
||||
|
@ -346,8 +379,3 @@ func killMountProcess() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
deleteCmd.Flags().BoolVar(&deleteAll, "all", false, "Set flag to delete all profiles")
|
||||
RootCmd.AddCommand(deleteCmd)
|
||||
}
|
||||
|
|
|
@ -22,450 +22,171 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/otiai10/copy"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
)
|
||||
|
||||
func TestDeleteProfileWithValidConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
// except returns a list of strings, minus the excluded ones
|
||||
func exclude(vals []string, exclude []string) []string {
|
||||
result := []string{}
|
||||
for _, v := range vals {
|
||||
excluded := false
|
||||
for _, e := range exclude {
|
||||
if e == v {
|
||||
excluded = true
|
||||
continue
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p1"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
if !excluded {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
return result
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithEmptyProfileConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
func fileNames(path string) ([]string, error) {
|
||||
result := []string{}
|
||||
fis, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
return result, err
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
for _, fi := range fis {
|
||||
result = append(result, fi.Name())
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p2_empty_profile_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithInvalidProfileConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
func TestDeleteProfile(t *testing.T) {
|
||||
td, err := ioutil.TempDir("", "single")
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
t.Fatalf("tempdir: %v", err)
|
||||
}
|
||||
err = copy.Copy("../../../pkg/minikube/config/testdata/delete-single", td)
|
||||
if err != nil {
|
||||
t.Fatalf("copy: %v", err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
tests := []struct {
|
||||
name string
|
||||
profile string
|
||||
expected []string
|
||||
}{
|
||||
{"normal", "p1", []string{"p1"}},
|
||||
{"empty-profile", "p2_empty_profile_config", []string{"p2_empty_profile_config"}},
|
||||
{"invalid-profile", "p3_invalid_profile_config", []string{"p3_invalid_profile_config"}},
|
||||
{"partial-profile", "p4_partial_profile_config", []string{"p4_partial_profile_config"}},
|
||||
{"missing-mach", "p5_missing_machine_config", []string{"p5_missing_machine_config"}},
|
||||
{"empty-mach", "p6_empty_machine_config", []string{"p6_empty_machine_config"}},
|
||||
{"invalid-mach", "p7_invalid_machine_config", []string{"p7_invalid_machine_config"}},
|
||||
{"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}},
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err = os.Setenv(localpath.MinikubeHome, td)
|
||||
if err != nil {
|
||||
t.Errorf("setenv: %v", err)
|
||||
}
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
beforeProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
if err != nil {
|
||||
t.Errorf("readdir: %v", err)
|
||||
}
|
||||
beforeMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
if err != nil {
|
||||
t.Errorf("readdir: %v", err)
|
||||
}
|
||||
|
||||
profileToDelete := "p3_invalid_profile_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
profile, err := config.LoadProfile(tt.profile)
|
||||
if err != nil {
|
||||
t.Logf("load failure: %v", err)
|
||||
}
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
t.Errorf("Errors while deleting profiles: %v", errs)
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
if err != nil {
|
||||
t.Errorf("readdir profiles: %v", err)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
afterMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
if err != nil {
|
||||
t.Errorf("readdir machines: %v", err)
|
||||
}
|
||||
|
||||
expectedProfiles := exclude(beforeProfiles, tt.expected)
|
||||
if diff := cmp.Diff(expectedProfiles, afterProfiles); diff != "" {
|
||||
t.Errorf("profiles mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
expectedMachines := exclude(beforeMachines, tt.expected)
|
||||
if diff := cmp.Diff(expectedMachines, afterMachines); diff != "" {
|
||||
t.Errorf("machines mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithPartialProfileConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
})
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p4_partial_profile_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithMissingMachineConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p5_missing_machine_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != numberOfMachineDirs {
|
||||
t.Fatal("Deleted a machine config when it should not")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithEmptyMachineConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p6_empty_machine_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithInvalidMachineConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p7_invalid_machine_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteProfileWithPartialMachineConfig(t *testing.T) {
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-single/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
profileToDelete := "p8_partial_machine_config"
|
||||
profile, _ := config.LoadProfile(profileToDelete)
|
||||
|
||||
errs := DeleteProfiles([]*config.Profile{profile})
|
||||
|
||||
if len(errs) > 0 {
|
||||
HandleDeletionErrors(errs)
|
||||
t.Fatal("Errors while deleting profiles")
|
||||
}
|
||||
|
||||
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
pathToMachine := cluster.MachinePath(profile.Name, localpath.MiniPath())
|
||||
if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
|
||||
t.Fatalf("Profile folder of profile \"%s\" was not deleted", profile.Name)
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles")); len(files) != (numberOfProfileDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
if files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines")); len(files) != (numberOfMachineDirs - 1) {
|
||||
t.Fatal("Did not delete exactly one profile")
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
}
|
||||
|
||||
func TestDeleteAllProfiles(t *testing.T) {
|
||||
const numberOfTotalProfileDirs = 8
|
||||
const numberOfTotalMachineDirs = 7
|
||||
|
||||
testMinikubeDir := "../../../pkg/minikube/config/testdata/delete-all/.minikube"
|
||||
miniDir, err := filepath.Abs(testMinikubeDir)
|
||||
|
||||
td, err := ioutil.TempDir("", "all")
|
||||
if err != nil {
|
||||
t.Errorf("error getting dir path for %s : %v", testMinikubeDir, err)
|
||||
t.Fatalf("tempdir: %v", err)
|
||||
}
|
||||
err = copy.Copy("../../../pkg/minikube/config/testdata/delete-all", td)
|
||||
if err != nil {
|
||||
t.Fatalf("copy: %v", err)
|
||||
}
|
||||
|
||||
err = os.Setenv(localpath.MinikubeHome, miniDir)
|
||||
err = os.Setenv(localpath.MinikubeHome, td)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
|
||||
}
|
||||
|
||||
files, _ := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs := len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs := len(files)
|
||||
|
||||
if numberOfTotalProfileDirs != numberOfProfileDirs {
|
||||
t.Error("invalid testdata")
|
||||
pFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
if err != nil {
|
||||
t.Errorf("filenames: %v", err)
|
||||
}
|
||||
mFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
if err != nil {
|
||||
t.Errorf("filenames: %v", err)
|
||||
}
|
||||
|
||||
if numberOfTotalMachineDirs != numberOfMachineDirs {
|
||||
t.Error("invalid testdata")
|
||||
const numberOfTotalProfileDirs = 8
|
||||
if numberOfTotalProfileDirs != len(pFiles) {
|
||||
t.Errorf("got %d test profiles, expected %d: %s", len(pFiles), numberOfTotalProfileDirs, pFiles)
|
||||
}
|
||||
const numberOfTotalMachineDirs = 7
|
||||
if numberOfTotalMachineDirs != len(mFiles) {
|
||||
t.Errorf("got %d test machines, expected %d: %s", len(mFiles), numberOfTotalMachineDirs, mFiles)
|
||||
}
|
||||
|
||||
validProfiles, inValidProfiles, err := config.ListProfiles()
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if numberOfTotalProfileDirs != len(validProfiles)+len(inValidProfiles) {
|
||||
t.Error("invalid testdata")
|
||||
t.Errorf("ListProfiles length = %d, expected %d\nvalid: %v\ninvalid: %v\n", len(validProfiles)+len(inValidProfiles), numberOfTotalProfileDirs, validProfiles, inValidProfiles)
|
||||
}
|
||||
|
||||
profiles := append(validProfiles, inValidProfiles...)
|
||||
|
@ -475,18 +196,20 @@ func TestDeleteAllProfiles(t *testing.T) {
|
|||
t.Errorf("errors while deleting all profiles: %v", errs)
|
||||
}
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
numberOfProfileDirs = len(files)
|
||||
|
||||
files, _ = ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
numberOfMachineDirs = len(files)
|
||||
|
||||
if numberOfProfileDirs != 0 {
|
||||
t.Errorf("Did not delete all profiles: still %d profiles left", numberOfProfileDirs)
|
||||
afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
|
||||
if err != nil {
|
||||
t.Errorf("profiles: %v", err)
|
||||
}
|
||||
afterMachines, err := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
|
||||
if err != nil {
|
||||
t.Errorf("machines: %v", err)
|
||||
}
|
||||
if len(afterProfiles) != 0 {
|
||||
t.Errorf("Did not delete all profiles, remaining: %v", afterProfiles)
|
||||
}
|
||||
|
||||
if numberOfMachineDirs != 0 {
|
||||
t.Errorf("Did not delete all profiles: still %d machines left", numberOfMachineDirs)
|
||||
if len(afterMachines) != 0 {
|
||||
t.Errorf("Did not delete all machines, remaining: %v", afterMachines)
|
||||
}
|
||||
|
||||
viper.Set(config.MachineProfile, "")
|
||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -37,6 +39,7 @@ import (
|
|||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
gopshost "github.com/shirou/gopsutil/host"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -117,6 +120,7 @@ const (
|
|||
minimumMemorySize = "1024mb"
|
||||
minimumCPUS = 2
|
||||
minimumDiskSize = "2000mb"
|
||||
autoUpdate = "auto-update-drivers"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -170,6 +174,7 @@ func initMinikubeFlags() {
|
|||
startCmd.Flags().Bool(waitUntilHealthy, true, "Wait until Kubernetes core services are healthy before exiting.")
|
||||
startCmd.Flags().Duration(waitTimeout, 6*time.Minute, "max time to wait per Kubernetes core services to be healthy.")
|
||||
startCmd.Flags().Bool(nativeSSH, true, "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'.")
|
||||
startCmd.Flags().Bool(autoUpdate, true, "If set, automatically updates drivers to the latest version. Defaults to true.")
|
||||
}
|
||||
|
||||
// initKubernetesFlags inits the commandline flags for kubernetes related options
|
||||
|
@ -293,7 +298,13 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
validateFlags(driver)
|
||||
validateUser(driver)
|
||||
|
||||
_ = getMinikubeVersion(driver)
|
||||
v, err := version.GetSemverVersion()
|
||||
if err != nil {
|
||||
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
|
||||
} else if err := drivers.InstallOrUpdate(driver, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive), viper.GetBool(autoUpdate)); err != nil {
|
||||
out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driver, "error": err})
|
||||
}
|
||||
|
||||
k8sVersion, isUpgrade := getKubernetesVersion(oldConfig)
|
||||
config, err := generateCfgFromFlags(cmd, k8sVersion, driver)
|
||||
if err != nil {
|
||||
|
@ -366,7 +377,9 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
exit.WithError("Wait failed", err)
|
||||
}
|
||||
}
|
||||
showKubectlConnectInfo(kubeconfig)
|
||||
if err := showKubectlInfo(kubeconfig, k8sVersion); err != nil {
|
||||
glog.Errorf("kubectl info: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func displayVersion(version string) {
|
||||
|
@ -446,8 +459,12 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma
|
|||
exit.WithError("Failed to get machine client", err)
|
||||
}
|
||||
host, preExists = startHost(m, config.MachineConfig)
|
||||
runner, err = machine.CommandRunner(host)
|
||||
if err != nil {
|
||||
exit.WithError("Failed to get command runner", err)
|
||||
}
|
||||
|
||||
ip := validateNetwork(host)
|
||||
ip := validateNetwork(host, runner)
|
||||
// Bypass proxy for minikube's vm host ip
|
||||
err = proxy.ExcludeIP(ip)
|
||||
if err != nil {
|
||||
|
@ -458,10 +475,6 @@ func startMachine(config *cfg.Config) (runner command.Runner, preExists bool, ma
|
|||
if err := saveConfig(config); err != nil {
|
||||
exit.WithError("Failed to save config", err)
|
||||
}
|
||||
runner, err = machine.CommandRunner(host)
|
||||
if err != nil {
|
||||
exit.WithError("Failed to get command runner", err)
|
||||
}
|
||||
|
||||
return runner, preExists, m, host
|
||||
}
|
||||
|
@ -477,16 +490,48 @@ func showVersionInfo(k8sVersion string, cr cruntime.Manager) {
|
|||
}
|
||||
}
|
||||
|
||||
func showKubectlConnectInfo(kcs *kubeconfig.Settings) {
|
||||
func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string) error {
|
||||
if kcs.KeepContext {
|
||||
out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName})
|
||||
} else {
|
||||
out.T(out.Ready, `Done! kubectl is now configured to use "{{.name}}"`, out.V{"name": cfg.GetMachineName()})
|
||||
}
|
||||
_, err := exec.LookPath("kubectl")
|
||||
|
||||
path, err := exec.LookPath("kubectl")
|
||||
if err != nil {
|
||||
out.T(out.Tip, "For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/")
|
||||
return nil
|
||||
}
|
||||
|
||||
j, err := exec.Command(path, "version", "--client", "--output=json").Output()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "exec")
|
||||
}
|
||||
|
||||
cv := struct {
|
||||
ClientVersion struct {
|
||||
GitVersion string `json:"gitVersion"`
|
||||
} `json:"clientVersion"`
|
||||
}{}
|
||||
err = json.Unmarshal(j, &cv)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unmarshal")
|
||||
}
|
||||
|
||||
client, err := semver.Make(strings.TrimPrefix(cv.ClientVersion.GitVersion, version.VersionPrefix))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "client semver")
|
||||
}
|
||||
|
||||
cluster := semver.MustParse(strings.TrimPrefix(k8sVersion, version.VersionPrefix))
|
||||
minorSkew := int(math.Abs(float64(int(client.Minor) - int(cluster.Minor))))
|
||||
glog.Infof("kubectl: %s, cluster: %s (minor skew: %d)", client, cluster, minorSkew)
|
||||
|
||||
if client.Major != cluster.Major || minorSkew > 1 {
|
||||
out.WarningT("{{.path}} is version {{.client_version}}, and is incompatible with Kubernetes {{.cluster_version}}. You will need to update {{.path}} or use 'minikube kubectl' to connect with this cluster",
|
||||
out.V{"path": path, "client_version": client, "cluster_version": cluster})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func selectDriver(oldConfig *cfg.Config) string {
|
||||
|
@ -764,7 +809,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, driver string)
|
|||
repository = autoSelectedRepository
|
||||
}
|
||||
|
||||
if repository != "" {
|
||||
if cmd.Flags().Changed(imageRepository) {
|
||||
out.T(out.SuccessType, "Using image repository {{.name}}", out.V{"name": repository})
|
||||
}
|
||||
|
||||
|
@ -905,7 +950,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) {
|
|||
}
|
||||
|
||||
// validateNetwork tries to catch network problems as soon as possible
|
||||
func validateNetwork(h *host.Host) string {
|
||||
func validateNetwork(h *host.Host, r command.Runner) string {
|
||||
ip, err := h.Driver.GetIP()
|
||||
if err != nil {
|
||||
exit.WithError("Unable to get VM IP address", err)
|
||||
|
@ -929,19 +974,52 @@ func validateNetwork(h *host.Host) string {
|
|||
}
|
||||
}
|
||||
|
||||
// Here is where we should be checking connectivity to/from the VM
|
||||
return ip
|
||||
}
|
||||
|
||||
// getMinikubeVersion ensures that the driver binary is up to date
|
||||
func getMinikubeVersion(driver string) string {
|
||||
v, err := version.GetSemverVersion()
|
||||
// none driver does not need ssh access
|
||||
if h.Driver.DriverName() != constants.DriverNone {
|
||||
sshAddr := fmt.Sprintf("%s:22", ip)
|
||||
conn, err := net.Dial("tcp", sshAddr)
|
||||
if err != nil {
|
||||
out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err})
|
||||
} else if err := drivers.InstallOrUpdate(driver, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive)); err != nil {
|
||||
out.WarningT("Unable to update {{.driver}} driver: {{.error}}", out.V{"driver": driver, "error": err})
|
||||
exit.WithCodeT(exit.IO, `minikube is unable to connect to the VM: {{.error}}
|
||||
|
||||
This is likely due to one of two reasons:
|
||||
|
||||
- VPN or firewall interference
|
||||
- {{.hypervisor}} network configuration issue
|
||||
|
||||
Suggested workarounds:
|
||||
|
||||
- Disable your local VPN or firewall software
|
||||
- Configure your local VPN or firewall to allow access to {{.ip}}
|
||||
- Restart or reinstall {{.hypervisor}}
|
||||
- Use an alternative --vm-driver`, out.V{"error": err, "hypervisor": h.Driver.DriverName(), "ip": ip})
|
||||
}
|
||||
return v.String()
|
||||
defer conn.Close()
|
||||
}
|
||||
|
||||
if err := r.Run("nslookup kubernetes.io"); err != nil {
|
||||
out.WarningT("VM is unable to resolve DNS hosts: {[.error}}", out.V{"error": err})
|
||||
}
|
||||
|
||||
// Try both UDP and ICMP to assert basic external connectivity
|
||||
if err := r.Run("nslookup k8s.io 8.8.8.8 || nslookup k8s.io 1.1.1.1 || ping -c1 8.8.8.8"); err != nil {
|
||||
out.WarningT("VM is unable to directly connect to the internet: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
|
||||
// Try an HTTPS connection to the
|
||||
proxy := os.Getenv("HTTPS_PROXY")
|
||||
opts := "-sS"
|
||||
if proxy != "" && !strings.HasPrefix(proxy, "localhost") && !strings.HasPrefix(proxy, "127.0") {
|
||||
opts = fmt.Sprintf("-x %s %s", proxy, opts)
|
||||
}
|
||||
|
||||
repo := viper.GetString(imageRepository)
|
||||
if repo == "" {
|
||||
repo = images.DefaultImageRepo
|
||||
}
|
||||
if err := r.Run(fmt.Sprintf("curl %s https://%s/", opts, repo)); err != nil {
|
||||
out.WarningT("VM is unable to connect to the selected image repository: {{.error}}", out.V{"error": err})
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
// getKubernetesVersion ensures that the requested version is reasonable
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "mkcmp [path to first binary] [path to second binary]",
|
||||
Short: "mkcmp is used to compare performance of two minikube binaries",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return validateArgs(args)
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {},
|
||||
}
|
||||
|
||||
func validateArgs(args []string) error {
|
||||
if len(args) != 2 {
|
||||
return errors.New("mkcmp requires two minikube binaries to compare: mkcmp [path to first binary] [path to second binary]")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute runs the mkcmp command
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "k8s.io/minikube/cmd/performance/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
|
@ -8,11 +8,11 @@ machine=$(uname -m)
|
|||
case ${machine} in
|
||||
aarch64 )
|
||||
TOOLBOX_DOCKER_IMAGE=arm64v8/fedora
|
||||
TOOLBOX_DOCKER_TAG=29
|
||||
TOOLBOX_DOCKER_TAG=latest
|
||||
;;
|
||||
x86_64 )
|
||||
TOOLBOX_DOCKER_IMAGE=fedora
|
||||
TOOLBOX_DOCKER_TAG=29
|
||||
TOOLBOX_DOCKER_TAG=latest
|
||||
;;
|
||||
* )
|
||||
echo "Warning: Unknown machine type ${machine}" >&2
|
||||
|
@ -69,10 +69,9 @@ if [ "x${1-}" == x-c ]; then
|
|||
set /bin/sh "$@"
|
||||
fi
|
||||
|
||||
sudo systemd-nspawn \
|
||||
sudo SYSTEMD_NSPAWN_SHARE_SYSTEM=1 systemd-nspawn \
|
||||
--directory="${machinepath}" \
|
||||
--capability=all \
|
||||
--share-system \
|
||||
${TOOLBOX_BIND} \
|
||||
${TOOLBOX_ENV} \
|
||||
--user="${TOOLBOX_USER}" "$@"
|
||||
|
|
3
go.mod
3
go.mod
|
@ -25,7 +25,6 @@ require (
|
|||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/google/go-cmp v0.3.0
|
||||
github.com/google/go-github/v25 v25.0.2
|
||||
github.com/gorilla/mux v1.7.1 // indirect
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect
|
||||
github.com/hashicorp/go-getter v1.3.0
|
||||
|
@ -50,6 +49,7 @@ require (
|
|||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
|
||||
github.com/moby/hyperkit v0.0.0-20171020124204-a12cd7250bcd
|
||||
github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd
|
||||
github.com/otiai10/copy v1.0.2
|
||||
github.com/pborman/uuid v1.2.0
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
|
||||
github.com/pkg/browser v0.0.0-20160118053552-9302be274faa
|
||||
|
@ -69,7 +69,6 @@ require (
|
|||
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb
|
||||
golang.org/x/text v0.3.2
|
||||
|
|
8
go.sum
8
go.sum
|
@ -195,8 +195,6 @@ github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e h1:Hm0
|
|||
github.com/google/go-containerregistry v0.0.0-20180731221751-697ee0b3d46e/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
|
||||
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/v25 v25.0.2 h1:MqXE7nOlIF91NJ/PXAcvS2dC+XXCDbY7RvJzjyEPAoU=
|
||||
github.com/google/go-github/v25 v25.0.2/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw=
|
||||
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/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
|
@ -383,6 +381,11 @@ github.com/opencontainers/runc v0.0.0-20181113202123-f000fe11ece1/go.mod h1:qT5X
|
|||
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v0.0.0-20170621221121-4a2974bf1ee9/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
|
||||
github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
@ -558,7 +561,6 @@ golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5Tlb
|
|||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
|
@ -2,7 +2,7 @@ Package: minikube
|
|||
Version: --VERSION--
|
||||
Section: base
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Architecture: --ARCH--
|
||||
Recommends: virtualbox
|
||||
Maintainer: Thomas Strömberg <t+minikube@stromberg.org>
|
||||
Description: Minikube
|
||||
|
|
|
@ -18,12 +18,12 @@ day-to-day.
|
|||
%prep
|
||||
mkdir -p %{name}-%{version}
|
||||
cd %{name}-%{version}
|
||||
cp --OUT--/minikube-linux-amd64 .
|
||||
cp --OUT--/minikube-linux-%{_arch} minikube
|
||||
|
||||
%install
|
||||
cd %{name}-%{version}
|
||||
mkdir -p %{buildroot}%{_bindir}
|
||||
install -m 755 minikube-linux-amd64 %{buildroot}%{_bindir}/%{name}
|
||||
install -m 755 minikube %{buildroot}%{_bindir}/%{name}
|
||||
|
||||
%files
|
||||
%{_bindir}/%{name}
|
||||
|
|
|
@ -149,14 +149,15 @@ func fixMachinePermissions(path string) error {
|
|||
}
|
||||
|
||||
// InstallOrUpdate downloads driver if it is not present, or updates it if there's a newer version
|
||||
func InstallOrUpdate(driver string, directory string, v semver.Version, interactive bool) error {
|
||||
func InstallOrUpdate(driver string, directory string, v semver.Version, interactive bool, autoUpdate bool) error {
|
||||
if driver != constants.DriverKvm2 && driver != constants.DriverHyperkit {
|
||||
return nil
|
||||
}
|
||||
|
||||
executable := fmt.Sprintf("docker-machine-driver-%s", driver)
|
||||
exists := driverExists(executable)
|
||||
path, err := validateDriver(executable, v)
|
||||
if err != nil {
|
||||
if !exists || (err != nil && autoUpdate) {
|
||||
glog.Warningf("%s: %v", executable, err)
|
||||
path = filepath.Join(directory, executable)
|
||||
derr := download(executable, path, v)
|
||||
|
@ -240,6 +241,11 @@ func validateDriver(driver string, v semver.Version) (string, error) {
|
|||
return path, nil
|
||||
}
|
||||
|
||||
func driverExists(driver string) bool {
|
||||
_, err := exec.LookPath(driver)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func driverWithChecksumURL(driver string, v semver.Version) string {
|
||||
base := fmt.Sprintf("https://github.com/kubernetes/minikube/releases/download/v%s/%s", v, driver)
|
||||
return fmt.Sprintf("%s?checksum=file:%s.sha256", base, base)
|
||||
|
|
|
@ -46,7 +46,7 @@ var (
|
|||
]`)
|
||||
)
|
||||
|
||||
func Test_parseStatusAndReturnIp(t *testing.T) {
|
||||
func TestParseStatusAndReturnIp(t *testing.T) {
|
||||
type args struct {
|
||||
mac string
|
||||
statuses []byte
|
||||
|
|
|
@ -420,7 +420,7 @@ func GenerateTemplateData(cfg config.KubernetesConfig) interface{} {
|
|||
// for less common architectures blank suffix for amd64
|
||||
ea := ""
|
||||
if runtime.GOARCH != "amd64" {
|
||||
ea = runtime.GOARCH
|
||||
ea = "-" + runtime.GOARCH
|
||||
}
|
||||
opts := struct {
|
||||
Arch string
|
||||
|
|
|
@ -25,10 +25,17 @@ import (
|
|||
minikubeVersion "k8s.io/minikube/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultImageRepo is the default repository for images
|
||||
DefaultImageRepo = "k8s.gcr.io"
|
||||
// DefaultMinikubeRepo is the default repository for minikube
|
||||
DefaultMinikubeRepo = "gcr.io/k8s-minikube"
|
||||
)
|
||||
|
||||
// getImageRepositories returns either the k8s image registry on GCR or a mirror if specified
|
||||
func getImageRepository(imageRepository string) string {
|
||||
if imageRepository == "" {
|
||||
imageRepository = "k8s.gcr.io"
|
||||
imageRepository = DefaultImageRepo
|
||||
}
|
||||
if !strings.HasSuffix(imageRepository, "/") {
|
||||
imageRepository += "/"
|
||||
|
@ -41,7 +48,7 @@ func getImageRepository(imageRepository string) string {
|
|||
func getMinikubeRepository(imageRepository string) string {
|
||||
minikubeRepository := imageRepository
|
||||
if minikubeRepository == "" {
|
||||
minikubeRepository = "gcr.io/k8s-minikube"
|
||||
minikubeRepository = DefaultMinikubeRepo
|
||||
}
|
||||
if !strings.HasSuffix(minikubeRepository, "/") {
|
||||
minikubeRepository += "/"
|
||||
|
|
|
@ -278,8 +278,10 @@ func DeleteHost(api libmachine.API) error {
|
|||
// Get the status of the host. Ensure that it exists before proceeding ahead.
|
||||
status, err := GetHostStatus(api)
|
||||
if err != nil {
|
||||
exit.WithCodeT(exit.Failure, "Unable to get the status of the cluster.")
|
||||
// Warn, but proceed
|
||||
out.WarningT("Unable to get the status of the {{.name}} cluster.", out.V{"name": cfg.GetMachineName()})
|
||||
}
|
||||
|
||||
if status == state.None.String() {
|
||||
return mcnerror.ErrHostDoesNotExist{Name: host.Name}
|
||||
}
|
||||
|
@ -289,6 +291,7 @@ func DeleteHost(api libmachine.API) error {
|
|||
if err := trySSHPowerOff(host); err != nil {
|
||||
glog.Infof("Unable to power off minikube because the host was not found.")
|
||||
}
|
||||
out.T(out.DeletingHost, "Successfully powered off Hyper-V. minikube driver -- {{.driver}}", out.V{"driver": host.Driver.DriverName()})
|
||||
}
|
||||
|
||||
out.T(out.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, out.V{"profile_name": cfg.GetMachineName(), "driver_name": host.DriverName})
|
||||
|
@ -602,8 +605,8 @@ func CreateSSHShell(api libmachine.API, args []string) error {
|
|||
return client.Shell(args...)
|
||||
}
|
||||
|
||||
// EnsureMinikubeRunningOrExit checks that minikube has a status available and that
|
||||
// the status is `Running`, otherwise it will exit
|
||||
// IsMinikubeRunning checks that minikube has a status available and that
|
||||
// the status is `Running`
|
||||
func IsMinikubeRunning(api libmachine.API) bool {
|
||||
s, err := GetHostStatus(api)
|
||||
if err != nil {
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// Machine contains information about a machine
|
||||
type Machine struct {
|
||||
*host.Host
|
||||
}
|
||||
|
@ -58,7 +59,7 @@ func (h *Machine) IsValid() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ListsMachines return all valid and invalid machines
|
||||
// ListMachines return all valid and invalid machines
|
||||
// If a machine is valid or invalid is determined by the cluster.IsValid function
|
||||
func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines []*Machine, err error) {
|
||||
pDirs, err := machineDirs(miniHome...)
|
||||
|
@ -80,7 +81,7 @@ func ListMachines(miniHome ...string) (validMachines []*Machine, inValidMachines
|
|||
return validMachines, inValidMachines, nil
|
||||
}
|
||||
|
||||
// Loads a machine or throws an error if the machine could not be loadedG
|
||||
// LoadMachine loads a machine or throws an error if the machine could not be loadedG
|
||||
func LoadMachine(name string) (*Machine, error) {
|
||||
api, err := machine.NewAPIClient()
|
||||
if err != nil {
|
||||
|
|
|
@ -174,7 +174,7 @@ func TestWriteConfig(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_encode(t *testing.T) {
|
||||
func TestEncode(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
for _, tt := range configTestCases {
|
||||
err := encode(&b, tt.config)
|
||||
|
|
|
@ -21,18 +21,20 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/util/lock"
|
||||
)
|
||||
|
||||
var keywords = []string{"start", "stop", "status", "delete", "config", "open", "profile", "addons", "cache", "logs"}
|
||||
|
||||
// IsValid checks if the profile has the essential info needed for a profile
|
||||
func (p *Profile) IsValid() bool {
|
||||
if p.Config == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Config.MachineConfig.VMDriver == "" {
|
||||
return false
|
||||
}
|
||||
|
@ -42,6 +44,16 @@ func (p *Profile) IsValid() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// check if the profile is an internal keywords
|
||||
func ProfileNameInReservedKeywords(name string) bool {
|
||||
for _, v := range keywords {
|
||||
if strings.EqualFold(v, name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ProfileExists returns true if there is a profile config (regardless of being valid)
|
||||
func ProfileExists(name string, miniHome ...string) bool {
|
||||
miniPath := localpath.MiniPath()
|
||||
|
@ -136,7 +148,7 @@ func ListProfiles(miniHome ...string) (validPs []*Profile, inValidPs []*Profile,
|
|||
return validPs, inValidPs, nil
|
||||
}
|
||||
|
||||
// loadProfile loads type Profile based on its name
|
||||
// LoadProfile loads type Profile based on its name
|
||||
func LoadProfile(name string, miniHome ...string) (*Profile, error) {
|
||||
cfg, err := DefaultLoader.LoadConfigFromFile(name, miniHome...)
|
||||
p := &Profile{
|
||||
|
|
|
@ -72,6 +72,32 @@ func TestListProfiles(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProfileNameInReservedKeywords(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
name string
|
||||
expected bool
|
||||
}{
|
||||
{"start", true},
|
||||
{"stop", true},
|
||||
{"status", true},
|
||||
{"delete", true},
|
||||
{"config", true},
|
||||
{"open", true},
|
||||
{"profile", true},
|
||||
{"addons", true},
|
||||
{"cache", true},
|
||||
{"logs", true},
|
||||
{"myprofile", false},
|
||||
{"log", false},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
got := ProfileNameInReservedKeywords(tt.name)
|
||||
if got != tt.expected {
|
||||
t.Errorf("expected ProfileNameInReservedKeywords(%s)=%t but got %t ", tt.name, tt.expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileExists(t *testing.T) {
|
||||
miniDir, err := filepath.Abs("./testdata/.minikube2")
|
||||
if err != nil {
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
registry.Register(registry.DriverDef{
|
||||
_ = registry.Register(registry.DriverDef{
|
||||
Name: constants.DriverHyperv,
|
||||
Builtin: true,
|
||||
ConfigCreator: createHypervHost,
|
||||
|
@ -45,7 +45,7 @@ func createHypervHost(config cfg.MachineConfig) interface{} {
|
|||
d.VSwitch = config.HypervVirtualSwitch
|
||||
d.MemSize = config.Memory
|
||||
d.CPU = config.CPUs
|
||||
d.DiskSize = int(config.DiskSize)
|
||||
d.DiskSize = config.DiskSize
|
||||
d.SSHUser = "docker"
|
||||
d.DisableDynamicMemory = true // default to disable dynamic memory as minikube is unlikely to work properly with dynamic memory
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ func TestCacheBinary(t *testing.T) {
|
|||
{
|
||||
desc: "ok kubeadm",
|
||||
version: "v1.16.0",
|
||||
osName: runtime.GOOS,
|
||||
osName: "linux",
|
||||
archName: runtime.GOARCH,
|
||||
binary: "kubeadm",
|
||||
err: false,
|
||||
|
|
|
@ -275,7 +275,7 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin
|
|||
chkSVC := func() error { return CheckService(namespace, service) }
|
||||
|
||||
if err := retry.Expo(chkSVC, time.Duration(interval)*time.Second, time.Duration(wait)*time.Second); err != nil {
|
||||
return errors.Wrapf(err, "Could not find finalized endpoint being pointed to by %s", service)
|
||||
return errors.Wrapf(err, "Service %s was not found in %q namespace. You may select another namespace by using 'minikube service %s -n <namespace>", service, namespace, service)
|
||||
}
|
||||
|
||||
serviceURL, err := GetServiceURLsForService(api, namespace, service, urlTemplate)
|
||||
|
|
|
@ -97,6 +97,27 @@ var serviceNamespaces = map[string]typed_core.ServiceInterface{
|
|||
"default": defaultNamespaceServiceInterface,
|
||||
}
|
||||
|
||||
var serviceNamespaceOther = map[string]typed_core.ServiceInterface{
|
||||
"default": nondefaultNamespaceServiceInterface,
|
||||
}
|
||||
|
||||
var nondefaultNamespaceServiceInterface = &MockServiceInterface{
|
||||
ServiceList: &core.ServiceList{
|
||||
Items: []core.Service{
|
||||
{
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
Name: "non-namespace-dashboard-no-ports",
|
||||
Namespace: "cannot_be_found_namespace",
|
||||
Labels: map[string]string{"mock": "mock"},
|
||||
},
|
||||
Spec: core.ServiceSpec{
|
||||
Ports: []core.ServicePort{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var defaultNamespaceServiceInterface = &MockServiceInterface{
|
||||
ServiceList: &core.ServiceList{
|
||||
Items: []core.Service{
|
||||
|
@ -893,3 +914,54 @@ func TestWaitAndMaybeOpenService(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitAndMaybeOpenServiceForNotDefaultNamspace(t *testing.T) {
|
||||
defaultAPI := &tests.MockAPI{
|
||||
FakeStore: tests.FakeStore{
|
||||
Hosts: map[string]*host.Host{
|
||||
config.GetMachineName(): {
|
||||
Name: config.GetMachineName(),
|
||||
Driver: &tests.MockDriver{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
defaultTemplate := template.Must(template.New("svc-template").Parse("http://{{.IP}}:{{.Port}}"))
|
||||
|
||||
var tests = []struct {
|
||||
description string
|
||||
api libmachine.API
|
||||
namespace string
|
||||
service string
|
||||
expected []string
|
||||
urlMode bool
|
||||
https bool
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
description: "correctly return empty serviceURLs",
|
||||
namespace: "default",
|
||||
service: "non-namespace-dashboard-no-ports",
|
||||
api: defaultAPI,
|
||||
expected: []string{},
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
defer revertK8sClient(K8s)
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
K8s = &MockClientGetter{
|
||||
servicesMap: serviceNamespaceOther,
|
||||
endpointsMap: endpointNamespaces,
|
||||
}
|
||||
err := WaitAndMaybeOpenService(test.api, test.namespace, test.service, defaultTemplate, test.urlMode, test.https, 1, 0)
|
||||
if test.err && err == nil {
|
||||
t.Fatalf("WaitAndMaybeOpenService expected to fail for test: %v", test)
|
||||
}
|
||||
if !test.err && err != nil {
|
||||
t.Fatalf("WaitAndMaybeOpenService not expected to fail but got err: %v", err)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ func (router *osRouter) parseTable(table []byte) routingTable {
|
|||
},
|
||||
line: line,
|
||||
}
|
||||
glog.V(4).Infof("adding line %s", tableLine)
|
||||
glog.V(4).Infof("adding line %v", tableLine)
|
||||
t = append(t, tableLine)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,13 +34,13 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/out"
|
||||
)
|
||||
|
||||
// ErrPrefix notes an error
|
||||
const ErrPrefix = "! "
|
||||
|
||||
// OutPrefix notes output
|
||||
const OutPrefix = "> "
|
||||
|
||||
const (
|
||||
// ErrPrefix notes an error
|
||||
ErrPrefix = "! "
|
||||
|
||||
// OutPrefix notes output
|
||||
OutPrefix = "> "
|
||||
|
||||
downloadURL = "https://storage.googleapis.com/minikube/releases/%s/minikube-%s-amd64%s"
|
||||
)
|
||||
|
||||
|
|
|
@ -115,6 +115,11 @@ no = 'Sorry to hear that. Please <a href="https://github.com/kubernetes/minikube
|
|||
url = "https://kubernetes.slack.com/messages/C1F5CT6Q1"
|
||||
icon = "fab fa-slack"
|
||||
desc = "Chat with other minikube users & developers"
|
||||
[[params.links.user]]
|
||||
name = "minikube-users mailing list"
|
||||
url = "https://groups.google.com/forum/#!forum/minikube-users"
|
||||
icon = "fas fa-envelope"
|
||||
desc = "Interact with the minikube Users here"
|
||||
|
||||
# Developer relevant links. These will show up on right side of footer and in the community page if you have one.
|
||||
[[params.links.developer]]
|
||||
|
@ -122,3 +127,8 @@ no = 'Sorry to hear that. Please <a href="https://github.com/kubernetes/minikube
|
|||
url = "https://github.com/kubernetes/minikube"
|
||||
icon = "fab fa-github"
|
||||
desc = "Development takes place here!"
|
||||
[[params.links.developer]]
|
||||
name = "minikube-dev mailing list"
|
||||
url = "https://groups.google.com/forum/#!forum/minikube-dev"
|
||||
icon = "fa fa-envelope"
|
||||
desc = "Contact the minikube Dev's here"
|
||||
|
|
|
@ -18,6 +18,30 @@ associated files.
|
|||
minikube delete [flags]
|
||||
```
|
||||
|
||||
##### Delete all profiles
|
||||
```
|
||||
minikube delete --all
|
||||
```
|
||||
|
||||
##### Delete profile & `.minikube` directory
|
||||
Do note that the following command only works if you have only 1 profile. If there are multiple profiles, the command will error out.
|
||||
```
|
||||
minikube delete --purge
|
||||
```
|
||||
|
||||
##### Delete all profiles & `.minikube` directory
|
||||
This will delete all the profiles and `.minikube` directory.
|
||||
```
|
||||
minikube delete --purge --all
|
||||
```
|
||||
|
||||
### Flags
|
||||
|
||||
```
|
||||
--all: Set flag to delete all profiles
|
||||
--purge: Set this flag to delete the '.minikube' folder from your user directory.
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
|
|
|
@ -82,6 +82,13 @@ func TestDownloadAndDeleteAll(t *testing.T) {
|
|||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
})
|
||||
// Delete should always succeed, even if previously partially or fully deleted.
|
||||
t.Run("DeleteAlwaysSucceeds", func(t *testing.T) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,20 @@ func TestAddons(t *testing.T) {
|
|||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Assert that disable/enable works offline
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "stop", "-p", profile))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "addons", "enable", "dashboard", "-p", profile))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "addons", "disable", "dashboard", "-p", profile))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
}
|
||||
|
||||
func validateIngressAddon(ctx context.Context, t *testing.T, profile string) {
|
||||
|
|
|
@ -84,7 +84,7 @@ func TestKVMDriverInstallOrUpdate(t *testing.T) {
|
|||
t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err)
|
||||
}
|
||||
|
||||
err = drivers.InstallOrUpdate("kvm2", dir, newerVersion, true)
|
||||
err = drivers.InstallOrUpdate("kvm2", dir, newerVersion, true, true)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err)
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ func TestHyperKitDriverInstallOrUpdate(t *testing.T) {
|
|||
t.Fatalf("Expected new semver. test: %v, got: %v", tc.name, err)
|
||||
}
|
||||
|
||||
err = drivers.InstallOrUpdate("hyperkit", dir, newerVersion, true)
|
||||
err = drivers.InstallOrUpdate("hyperkit", dir, newerVersion, true, true)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to update driver to %v. test: %s, got: %v", newerVersion, tc.name, err)
|
||||
}
|
||||
|
|
|
@ -297,12 +297,48 @@ func validateLogsCmd(ctx context.Context, t *testing.T, profile string) {
|
|||
}
|
||||
}
|
||||
|
||||
// validateProfileCmd asserts basic "profile" command functionality
|
||||
// validateProfileCmd asserts "profile" command functionality
|
||||
func validateProfileCmd(ctx context.Context, t *testing.T, profile string) {
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "profile", "list"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
|
||||
// Table output
|
||||
listLines := strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n")
|
||||
profileExists := false
|
||||
for i := 3; i < (len(listLines) - 1); i++ {
|
||||
profileLine := listLines[i]
|
||||
if strings.Contains(profileLine, profile) {
|
||||
profileExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !profileExists {
|
||||
t.Errorf("%s failed: Missing profile '%s'. Got '\n%s\n'", rr.Args, profile, rr.Stdout.String())
|
||||
}
|
||||
|
||||
// Json output
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "profile", "list", "--output", "json"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
var jsonObject map[string][]map[string]interface{}
|
||||
err = json.Unmarshal(rr.Stdout.Bytes(), &jsonObject)
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
validProfiles := jsonObject["valid"]
|
||||
profileExists = false
|
||||
for _, profileObject := range validProfiles {
|
||||
if profileObject["Name"] == profile {
|
||||
profileExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !profileExists {
|
||||
t.Errorf("%s failed: Missing profile '%s'. Got '\n%s\n'", rr.Args, profile, rr.Stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
// validateServiceCmd asserts basic "service" command functionality
|
||||
|
@ -360,6 +396,17 @@ func validateAddonsCmd(ctx context.Context, t *testing.T, profile string) {
|
|||
t.Errorf("Plugin output did not match expected custom format. Got: %s", line)
|
||||
}
|
||||
}
|
||||
|
||||
// Json output
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "-o", "json"))
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
var jsonObject map[string]interface{}
|
||||
err = json.Unmarshal(rr.Stdout.Bytes(), &jsonObject)
|
||||
if err != nil {
|
||||
t.Errorf("%s failed: %v", rr.Args, err)
|
||||
}
|
||||
}
|
||||
|
||||
// validateSSHCmd asserts basic "ssh" command functionality
|
||||
|
|
|
@ -23,14 +23,12 @@ func atime(stat *syscall.Stat_t) time.Time {
|
|||
func isBlock(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK
|
||||
return true
|
||||
}
|
||||
|
||||
// IsChar reports if the file is a character device
|
||||
func isChar(d os.FileInfo) bool {
|
||||
stat := d.Sys().(*syscall.Stat_t)
|
||||
return (stat.Mode & syscall.S_IFMT) == syscall.S_IFCHR
|
||||
return true
|
||||
}
|
||||
|
||||
func dir2Qid(d os.FileInfo) *Qid {
|
||||
|
|
|
@ -218,7 +218,7 @@ func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
|
|||
goto szerror
|
||||
}
|
||||
|
||||
return
|
||||
return //NOSONAR
|
||||
|
||||
szerror:
|
||||
return nil, &Error{"invalid size", EINVAL}, 0
|
||||
|
|
Loading…
Reference in New Issue