Remove error uploads, consolidate fatal error handling into exit package

pull/3661/head
Thomas Stromberg 2019-02-13 12:37:44 -08:00
parent ade3515f4f
commit 5f65dc80fa
35 changed files with 186 additions and 523 deletions

View File

@ -17,13 +17,11 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -42,13 +40,11 @@ var addCacheCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Cache and load images into docker daemon // Cache and load images into docker daemon
if err := machine.CacheAndLoadImages(args); err != nil { if err := machine.CacheAndLoadImages(args); err != nil {
console.Fatal("Failed to cache and load images: %v", err) exit.WithError("Failed to cache and load images", err)
os.Exit(1)
} }
// Add images to config file // Add images to config file
if err := cmdConfig.AddToConfigMap(constants.Cache, args); err != nil { if err := cmdConfig.AddToConfigMap(constants.Cache, args); err != nil {
console.Fatal("Failed to update config: %v", err) exit.WithError("Failed to update config", err)
os.Exit(1)
} }
}, },
} }
@ -61,13 +57,11 @@ var deleteCacheCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Delete images from config file // Delete images from config file
if err := cmdConfig.DeleteFromConfigMap(constants.Cache, args); err != nil { if err := cmdConfig.DeleteFromConfigMap(constants.Cache, args); err != nil {
console.Fatal("Failed to delete images from config: %v", err) exit.WithError("Failed to delete images from config", err)
os.Exit(1)
} }
// Delete images from cache/images directory // Delete images from cache/images directory
if err := machine.DeleteFromImageCacheDir(args); err != nil { if err := machine.DeleteFromImageCacheDir(args); err != nil {
console.Fatal("Failed to delete images: %v", err) exit.WithError("Failed to delete images", err)
os.Exit(1)
} }
}, },
} }

View File

@ -22,8 +22,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
) )
var cacheListFormat string var cacheListFormat string
@ -40,12 +40,10 @@ var listCacheCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
images, err := cmdConfig.ListConfigMap(constants.Cache) images, err := cmdConfig.ListConfigMap(constants.Cache)
if err != nil { if err != nil {
console.Fatal("Failed to get image map: %v", err) exit.WithError("Failed to get image map", err)
os.Exit(1)
} }
if err := cacheList(images); err != nil { if err := cacheList(images); err != nil {
console.Fatal("Failed to list cached images: %v", err) exit.WithError("Failed to list cached images", err)
os.Exit(1)
} }
}, },
} }
@ -61,14 +59,12 @@ func cacheList(images []string) error {
for _, image := range images { for _, image := range images {
tmpl, err := template.New("list").Parse(cacheListFormat) tmpl, err := template.New("list").Parse(cacheListFormat)
if err != nil { if err != nil {
console.Fatal("Unable to parse template: %v", err) exit.WithError("Unable to parse template", err)
os.Exit(1)
} }
listTmplt := CacheListTemplate{image} listTmplt := CacheListTemplate{image}
err = tmpl.Execute(os.Stdout, listTmplt) err = tmpl.Execute(os.Stdout, listTmplt)
if err != nil { if err != nil {
console.Fatal("Unable to process template: %v", err) exit.WithError("Unable to process template", err)
os.Exit(1)
} }
} }
return nil return nil

View File

@ -23,8 +23,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdutil "k8s.io/minikube/cmd/util" "k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/console"
) )
const longDescription = ` const longDescription = `
@ -70,21 +69,19 @@ var completionCmd = &cobra.Command{
Long: longDescription, Long: longDescription,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "Usage: minikube completion SHELL") exit.Usage("Usage: minikube completion SHELL")
os.Exit(1)
} }
if args[0] != "bash" && args[0] != "zsh" { if args[0] != "bash" && args[0] != "zsh" {
console.Fatal("Sorry, completion support is not yet implemented for %q", args[0]) exit.Usage("Sorry, completion support is not yet implemented for %q", args[0])
os.Exit(1)
} else if args[0] == "bash" { } else if args[0] == "bash" {
err := GenerateBashCompletion(os.Stdout, cmd.Parent()) err := GenerateBashCompletion(os.Stdout, cmd.Parent())
if err != nil { if err != nil {
cmdutil.MaybeReportErrorAndExit(err) exit.WithError("bash completion failed", err)
} }
} else { } else {
err := GenerateZshCompletion(os.Stdout, cmd.Parent()) err := GenerateZshCompletion(os.Stdout, cmd.Parent())
if err != nil { if err != nil {
cmdutil.MaybeReportErrorAndExit(err) exit.WithError("zsh completion failed", err)
} }
} }

View File

@ -21,11 +21,10 @@ import (
"sort" "sort"
"text/template" "text/template"
"github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
) )
var addonListFormat string var addonListFormat string
@ -41,13 +40,11 @@ var addonsListCmd = &cobra.Command{
Long: "Lists all available minikube addons as well as their current statuses (enabled/disabled)", Long: "Lists all available minikube addons as well as their current statuses (enabled/disabled)",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 0 { if len(args) != 0 {
console.ErrStyle("usage", "usage: minikube addons list") exit.Usage("usage: minikube addons list")
os.Exit(1)
} }
err := addonList() err := addonList()
if err != nil { if err != nil {
console.Fatal("addon list failed: %v", err) exit.WithError("addon list failed", err)
os.Exit(1)
} }
}, },
} }
@ -81,14 +78,12 @@ func addonList() error {
} }
tmpl, err := template.New("list").Parse(addonListFormat) tmpl, err := template.New("list").Parse(addonListFormat)
if err != nil { if err != nil {
glog.Errorln("Error creating list template:", err) exit.WithError("Error creating list template", err)
os.Exit(1)
} }
listTmplt := AddonListTemplate{addonName, stringFromStatus(addonStatus)} listTmplt := AddonListTemplate{addonName, stringFromStatus(addonStatus)}
err = tmpl.Execute(os.Stdout, listTmplt) err = tmpl.Execute(os.Stdout, listTmplt)
if err != nil { if err != nil {
glog.Errorln("Error executing list template:", err) exit.WithError("Error executing list template", err)
os.Exit(1)
} }
} }
return nil return nil

View File

@ -20,11 +20,10 @@ import (
"os" "os"
"text/template" "text/template"
"github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
) )
var configViewFormat string var configViewFormat string
@ -41,8 +40,7 @@ var configViewCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := configView() err := configView()
if err != nil { if err != nil {
console.Fatal("config view failed: %v", err) exit.WithError("config view failed", err)
os.Exit(1)
} }
}, },
} }
@ -62,14 +60,12 @@ func configView() error {
for k, v := range cfg { for k, v := range cfg {
tmpl, err := template.New("view").Parse(configViewFormat) tmpl, err := template.New("view").Parse(configViewFormat)
if err != nil { if err != nil {
glog.Errorln("Error creating view template:", err) exit.WithError("Error creating view template", err)
os.Exit(1)
} }
viewTmplt := ConfigViewTemplate{k, v} viewTmplt := ConfigViewTemplate{k, v}
err = tmpl.Execute(os.Stdout, viewTmplt) err = tmpl.Execute(os.Stdout, viewTmplt)
if err != nil { if err != nil {
glog.Errorln("Error executing view template:", err) exit.WithError("Error executing view template", err)
os.Exit(1)
} }
} }
return nil return nil

View File

@ -18,10 +18,10 @@ package config
import ( import (
"io/ioutil" "io/ioutil"
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
) )
@ -31,8 +31,7 @@ var addonsConfigureCmd = &cobra.Command{
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 ", 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) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube addons configure ADDON_NAME") exit.Usage("usage: minikube addons configure ADDON_NAME")
os.Exit(1)
} }
addon := args[0] addon := args[0]

View File

@ -17,10 +17,9 @@ limitations under the License.
package config package config
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
) )
var addonsDisableCmd = &cobra.Command{ var addonsDisableCmd = &cobra.Command{
@ -29,15 +28,13 @@ var addonsDisableCmd = &cobra.Command{
Long: "Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list ", Long: "Disables the addon w/ADDON_NAME within minikube (example: minikube addons disable dashboard). For a list of available addons use: minikube addons list ",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube addons disable ADDON_NAME") exit.Usage("usage: minikube addons disable ADDON_NAME")
os.Exit(1)
} }
addon := args[0] addon := args[0]
err := Set(addon, "false") err := Set(addon, "false")
if err != nil { if err != nil {
console.Fatal("disable failed: %v", err) exit.WithError("disable failed", err)
os.Exit(1)
} }
console.Success("%s was successfully disabled", addon) console.Success("%s was successfully disabled", addon)
}, },

View File

@ -17,10 +17,9 @@ limitations under the License.
package config package config
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
) )
var addonsEnableCmd = &cobra.Command{ var addonsEnableCmd = &cobra.Command{
@ -29,8 +28,7 @@ var addonsEnableCmd = &cobra.Command{
Long: "Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list ", Long: "Enables the addon w/ADDON_NAME within minikube (example: minikube addons enable dashboard). For a list of available addons use: minikube addons list ",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube addons enable ADDON_NAME") exit.Usage("usage: minikube addons enable ADDON_NAME")
os.Exit(1)
} }
addon := args[0] addon := args[0]

View File

@ -25,6 +25,7 @@ import (
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
) )
@ -47,43 +48,38 @@ var addonsOpenCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
t, err := template.New("addonsURL").Parse(addonsURLFormat) t, err := template.New("addonsURL").Parse(addonsURLFormat)
if err != nil { if err != nil {
console.Fatal("The value passed to --format is invalid: %s", err) exit.Usage("The value passed to --format is invalid: %s", err)
os.Exit(1)
} }
addonsURLTemplate = t addonsURLTemplate = t
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube addons open ADDON_NAME") exit.Usage("usage: minikube addons open ADDON_NAME")
os.Exit(1)
} }
addonName := args[0] addonName := args[0]
//TODO(r2d4): config should not reference API, pull this out //TODO(r2d4): config should not reference API, pull this out
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 1) cluster.EnsureMinikubeRunningOrExit(api, 1)
addon, ok := assets.Addons[addonName] // validate addon input addon, ok := assets.Addons[addonName] // validate addon input
if !ok { if !ok {
console.Fatal(`addon '%s' is not a valid addon packaged with minikube. exit.WithCode(exit.Data, `addon '%s' is not a valid addon packaged with minikube.
To see the list of available addons run: To see the list of available addons run:
minikube addons list`, addonName) minikube addons list`, addonName)
os.Exit(1)
} }
ok, err = addon.IsEnabled() ok, err = addon.IsEnabled()
if err != nil { if err != nil {
console.Fatal("IsEnabled error: %v", err) exit.WithError("IsEnabled failed", err)
os.Exit(1)
} }
if !ok { if !ok {
console.ErrStyle("conflict", `addon '%s' is currently not enabled. console.ErrStyle("conflict", `addon '%s' is currently not enabled.
To enable this addon run: To enable this addon run:
minikube addons enable %s`, addonName, addonName) minikube addons enable %s`, addonName, addonName)
os.Exit(1) os.Exit(exit.Unavailable)
} }
namespace := "kube-system" namespace := "kube-system"
@ -91,15 +87,11 @@ minikube addons enable %s`, addonName, addonName)
serviceList, err := service.GetServiceListByLabel(namespace, key, addonName) serviceList, err := service.GetServiceListByLabel(namespace, key, addonName)
if err != nil { if err != nil {
console.Fatal("Error getting service with namespace: %s and labels %s:%s: %v", namespace, key, addonName, err) exit.Fail("Error getting service with namespace: %s and labels %s:%s: %v", namespace, key, addonName, err)
os.Exit(1)
} }
if len(serviceList.Items) == 0 { if len(serviceList.Items) == 0 {
console.Fatal(` exit.WithCode(exit.Config, `This addon does not have an endpoint defined for the 'addons open' command.
This addon does not have an endpoint defined for the 'addons open' command You can add one by annotating a service with the label %s:%s`, key, addonName)
You can add one by annotating a service with the label %s:%s
`, key, addonName)
os.Exit(1)
} }
for i := range serviceList.Items { for i := range serviceList.Items {
svc := serviceList.Items[i].ObjectMeta.Name svc := serviceList.Items[i].ObjectMeta.Name

View File

@ -17,11 +17,10 @@ limitations under the License.
package config package config
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
pkgConfig "k8s.io/minikube/pkg/minikube/config" pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
) )
var ProfileCmd = &cobra.Command{ var ProfileCmd = &cobra.Command{
@ -30,8 +29,7 @@ var ProfileCmd = &cobra.Command{
Long: "profile sets the current minikube profile. This is used to run and manage multiple minikube instance. You can return to the default minikube profile by running `minikube profile default`", Long: "profile sets the current minikube profile. This is used to run and manage multiple minikube instance. You can return to the default minikube profile by running `minikube profile default`",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube profile MINIKUBE_PROFILE_NAME") exit.Usage("usage: minikube profile MINIKUBE_PROFILE_NAME")
os.Exit(1)
} }
profile := args[0] profile := args[0]
@ -40,8 +38,7 @@ var ProfileCmd = &cobra.Command{
} }
err := Set(pkgConfig.MachineProfile, profile) err := Set(pkgConfig.MachineProfile, profile)
if err != nil { if err != nil {
console.Fatal("set failed: %v", err) exit.WithError("set failed", err)
os.Exit(1)
} else { } else {
console.Success("minikube profile was successfully set to %s", profile) console.Success("minikube profile was successfully set to %s", profile)
} }

View File

@ -17,11 +17,9 @@ limitations under the License.
package config package config
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
pkgConfig "k8s.io/minikube/pkg/minikube/config" pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/exit"
) )
var configSetCmd = &cobra.Command{ var configSetCmd = &cobra.Command{
@ -31,13 +29,11 @@ var configSetCmd = &cobra.Command{
These values can be overwritten by flags or environment variables at runtime.`, These values can be overwritten by flags or environment variables at runtime.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 { if len(args) != 2 {
console.ErrStyle("usage", "usage: minikube config set PROPERTY_NAME PROPERTY_VALUE") exit.Usage("usage: minikube config set PROPERTY_NAME PROPERTY_VALUE")
os.Exit(1)
} }
err := Set(args[0], args[1]) err := Set(args[0], args[1])
if err != nil { if err != nil {
console.Fatal("Set failed: %v", err) exit.WithError("Set failed", err)
os.Exit(1)
} }
}, },
} }

View File

@ -17,11 +17,9 @@ limitations under the License.
package config package config
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
pkgConfig "k8s.io/minikube/pkg/minikube/config" pkgConfig "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/exit"
) )
var configUnsetCmd = &cobra.Command{ var configUnsetCmd = &cobra.Command{
@ -30,12 +28,11 @@ var configUnsetCmd = &cobra.Command{
Long: "unsets PROPERTY_NAME from the minikube config file. Can be overwritten by flags or environmental variables", Long: "unsets PROPERTY_NAME from the minikube config file. Can be overwritten by flags or environmental variables",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", "usage: minikube config unset PROPERTY_NAME") exit.Usage("usage: minikube config unset PROPERTY_NAME")
os.Exit(1)
} }
err := unset(args[0]) err := unset(args[0])
if err != nil { if err != nil {
console.Fatal("unset failed: %v", err) exit.WithError("unset failed", err)
} }
}, },
} }

View File

@ -18,7 +18,6 @@ package config
import ( import (
"fmt" "fmt"
"os"
"strconv" "strconv"
"strings" "strings"
@ -26,7 +25,6 @@ import (
"k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/storageclass" "k8s.io/minikube/pkg/minikube/storageclass"
@ -106,8 +104,7 @@ func EnableOrDisableAddon(name string, val string) error {
//TODO(r2d4): config package should not reference API, pull this out //TODO(r2d4): config package should not reference API, pull this out
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) return errors.Wrap(err, "machine client")
os.Exit(1)
} }
defer api.Close() defer api.Close()
cluster.EnsureMinikubeRunningOrExit(api, 0) cluster.EnsureMinikubeRunningOrExit(api, 0)

View File

@ -21,7 +21,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"os"
"os/exec" "os/exec"
"regexp" "regexp"
"time" "time"
@ -34,6 +33,7 @@ import (
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
"k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util"
@ -61,8 +61,7 @@ var dashboardCmd = &cobra.Command{
}() }()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
cluster.EnsureMinikubeRunningOrExit(api, 1) cluster.EnsureMinikubeRunningOrExit(api, 1)
@ -71,29 +70,26 @@ var dashboardCmd = &cobra.Command{
// Enable the dashboard add-on // Enable the dashboard add-on
err = configcmd.Set("dashboard", "true") err = configcmd.Set("dashboard", "true")
if err != nil { if err != nil {
console.Fatal("Unable to enable dashboard: %v", err) exit.WithError("Unable to enable dashboard", err)
os.Exit(1)
} }
ns := "kube-system" ns := "kube-system"
svc := "kubernetes-dashboard" svc := "kubernetes-dashboard"
console.ErrStyle("verifying", "Verifying dashboard health ...") console.ErrStyle("verifying", "Verifying dashboard health ...")
if err = util.RetryAfter(180, func() error { return service.CheckService(ns, svc) }, 1*time.Second); err != nil { if err = util.RetryAfter(180, func() error { return service.CheckService(ns, svc) }, 1*time.Second); err != nil {
console.Fatal("%s:%s is not running: %v", ns, svc, err) exit.WithCode(exit.Unavailable, "%s:%s is not running: %v", ns, svc, err)
os.Exit(1)
} }
console.ErrStyle("launch", "Launching proxy ...") console.ErrStyle("launch", "Launching proxy ...")
p, hostPort, err := kubectlProxy() p, hostPort, err := kubectlProxy()
if err != nil { if err != nil {
glog.Fatalf("kubectl proxy: %v", err) exit.WithError("kubectl proxy", err)
} }
url := dashboardURL(hostPort, ns, svc) url := dashboardURL(hostPort, ns, svc)
console.ErrStyle("verifying", "Verifying proxy health ...") console.ErrStyle("verifying", "Verifying proxy health ...")
if err = util.RetryAfter(60, func() error { return checkURL(url) }, 1*time.Second); err != nil { if err = util.RetryAfter(60, func() error { return checkURL(url) }, 1*time.Second); err != nil {
console.Fatal("%s is not responding properly: %v", url, err) exit.WithCode(exit.Unavailable, "%s is not responding properly: %v", url, err)
os.Exit(1)
} }
if dashboardURLMode { if dashboardURLMode {

View File

@ -29,6 +29,7 @@ import (
pkg_config "k8s.io/minikube/pkg/minikube/config" pkg_config "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -40,14 +41,12 @@ var deleteCmd = &cobra.Command{
associated files.`, associated files.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) > 0 { if len(args) > 0 {
console.ErrStyle("usage", "usage: minikube delete") exit.Usage("usage: minikube delete")
os.Exit(1)
} }
profile := viper.GetString(pkg_config.MachineProfile) profile := viper.GetString(pkg_config.MachineProfile)
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
@ -72,8 +71,7 @@ associated files.`,
case mcnerror.ErrHostDoesNotExist: case mcnerror.ErrHostDoesNotExist:
console.OutStyle("meh", "%q VM does not exist", profile) console.OutStyle("meh", "%q VM does not exist", profile)
default: default:
console.Fatal("Failed to delete VM: %v", err) exit.WithError("Failed to delete VM", err)
os.Exit(1)
} }
} else { } else {
console.OutStyle("crushed", "VM deleted.") console.OutStyle("crushed", "VM deleted.")
@ -88,8 +86,7 @@ associated files.`,
console.OutStyle("meh", "%q profile does not exist", profile) console.OutStyle("meh", "%q profile does not exist", profile)
os.Exit(0) os.Exit(0)
} }
console.Fatal("Failed to remove profile: %v", err) exit.WithError("Failed to remove profile", err)
os.Exit(1)
} }
console.Success("Removed %q profile!", profile) console.Success("Removed %q profile!", profile)
}, },

View File

@ -28,14 +28,12 @@ import (
"github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/host"
"github.com/docker/machine/libmachine/shell" "github.com/docker/machine/libmachine/shell"
"github.com/golang/glog"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -311,23 +309,19 @@ var dockerEnvCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName())
if err != nil { if err != nil {
console.Fatal("Error getting host: %v", err) exit.WithError("Error getting host", err)
os.Exit(1)
} }
if host.Driver.DriverName() == "none" { if host.Driver.DriverName() == "none" {
console.Fatal(`'none' driver does not support 'minikube docker-env' command`) exit.Usage(`'none' driver does not support 'minikube docker-env' command`)
os.Exit(1)
} }
docker, err := GetDockerActive(host) docker, err := GetDockerActive(host)
if !docker { if !docker {
console.OutLn(`# The docker service is currently not active`) exit.WithCode(exit.Unavailable, `# The docker service is currently not active`)
os.Exit(1)
} }
var shellCfg *ShellConfig var shellCfg *ShellConfig
@ -335,14 +329,12 @@ var dockerEnvCmd = &cobra.Command{
if unset { if unset {
shellCfg, err = shellCfgUnset() shellCfg, err = shellCfgUnset()
if err != nil { if err != nil {
glog.Errorln("Error setting machine env variable(s):", err) exit.WithError("Error unsetting shell variables", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
} else { } else {
shellCfg, err = shellCfgSet(api) shellCfg, err = shellCfgSet(api)
if err != nil { if err != nil {
glog.Errorln("Error setting machine env variable(s):", err) exit.WithError("Error setting shell variables", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
} }

View File

@ -17,11 +17,12 @@ limitations under the License.
package cmd package cmd
import ( import (
"os" "github.com/docker/machine/libmachine/mcnerror"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -33,19 +34,22 @@ var ipCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
host, err := api.Load(config.GetMachineName()) host, err := api.Load(config.GetMachineName())
if err != nil { if err != nil {
console.Fatal("Error getting host: %v", err) switch err := errors.Cause(err).(type) {
os.Exit(1) case mcnerror.ErrHostDoesNotExist:
exit.WithCode(exit.NoInput, "%q host does not exist, unable to show an IP", config.GetMachineName())
default:
exit.WithError("Error getting host", err)
}
} }
ip, err := host.Driver.GetIP() ip, err := host.Driver.GetIP()
if err != nil { if err != nil {
console.Fatal("Error getting IP: %v", err) exit.WithError("Error getting IP", err)
os.Exit(1)
} }
console.OutLn(ip) console.OutLn(ip)
}, },

View File

@ -19,12 +19,10 @@ package cmd
import ( import (
"os" "os"
"github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
cmdUtil "k8s.io/minikube/cmd/util" "k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -40,19 +38,17 @@ var logsCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper))
if err != nil { if err != nil {
glog.Exitf("Error getting cluster bootstrapper: %v", err) exit.WithError("Error getting cluster bootstrapper", err)
} }
err = clusterBootstrapper.GetClusterLogsTo(follow, os.Stdout) err = clusterBootstrapper.GetClusterLogsTo(follow, os.Stdout)
if err != nil { if err != nil {
console.Fatal("Error getting machine logs:", err) exit.WithError("Error getting machine logs", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
}, },
} }

View File

@ -29,6 +29,7 @@ import (
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/third_party/go9p/ufs" "k8s.io/minikube/third_party/go9p/ufs"
) )
@ -48,37 +49,32 @@ var mountCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if isKill { if isKill {
if err := cmdUtil.KillMountProcess(); err != nil { if err := cmdUtil.KillMountProcess(); err != nil {
console.Fatal("Error killing mount process: ", err) exit.WithError("Error killing mount process", err)
os.Exit(1)
} }
os.Exit(0) os.Exit(0)
} }
if len(args) != 1 { if len(args) != 1 {
console.ErrStyle("usage", `Please specify the directory to be mounted: exit.Usage(`Please specify the directory to be mounted:
minikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home")`) minikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home")`)
os.Exit(1)
} }
mountString := args[0] mountString := args[0]
idx := strings.LastIndex(mountString, ":") idx := strings.LastIndex(mountString, ":")
if idx == -1 { // no ":" was present if idx == -1 { // no ":" was present
console.ErrStyle("usage", `Mount directory must be in the form: exit.Usage(`Mount directory must be in the form:
HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY`) HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY`)
os.Exit(1)
} }
hostPath := mountString[:idx] hostPath := mountString[:idx]
vmPath := mountString[idx+1:] vmPath := mountString[idx+1:]
if _, err := os.Stat(hostPath); err != nil { if _, err := os.Stat(hostPath); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
console.Fatal("Cannot find directory %s for mount", hostPath) exit.WithCode(exit.NoInput, "Cannot find directory %s for mount", hostPath)
} else { } else {
console.Fatal("Error accessing directory %s for mount", hostPath) exit.WithError("stat failed", err)
} }
os.Exit(1)
} }
if len(vmPath) == 0 || !strings.HasPrefix(vmPath, "/") { if len(vmPath) == 0 || !strings.HasPrefix(vmPath, "/") {
console.ErrStyle("usage", "The :VM_MOUNT_DIRECTORY must be an absolute path") exit.Usage("The :VM_MOUNT_DIRECTORY must be an absolute path")
os.Exit(1)
} }
var debugVal int var debugVal int
if glog.V(1) { if glog.V(1) {
@ -86,39 +82,33 @@ var mountCmd = &cobra.Command{
} }
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
host, err := api.Load(config.GetMachineName()) host, err := api.Load(config.GetMachineName())
if err != nil { if err != nil {
console.Fatal("Error loading api: %v", err) exit.WithError("Error loading api", err)
os.Exit(1)
} }
if host.Driver.DriverName() == "none" { if host.Driver.DriverName() == "none" {
console.Fatal(`'none' driver does not support 'minikube mount' command`) exit.Usage(`'none' driver does not support 'minikube mount' command`)
os.Exit(0)
} }
var ip net.IP var ip net.IP
if mountIP == "" { if mountIP == "" {
ip, err = cluster.GetVMHostIP(host) ip, err = cluster.GetVMHostIP(host)
if err != nil { if err != nil {
glog.Errorln("Error getting the host IP address to use from within the VM: ", err) exit.WithError("Error getting the host IP address to use from within the VM", err)
os.Exit(1)
} }
} else { } else {
ip = net.ParseIP(mountIP) ip = net.ParseIP(mountIP)
if ip == nil { if ip == nil {
glog.Errorln("error parsing the input ip address for mount") exit.WithCode(exit.Data, "error parsing the input ip address for mount")
os.Exit(1)
} }
} }
console.OutStyle("mounting", "Mounting %s into %s on the minikube VM", hostPath, vmPath) console.OutStyle("mounting", "Mounting %s into %s on the minikube VM", hostPath, vmPath)
console.OutStyle("notice", "This daemon process needs to stay alive for the mount to be accessible ...") console.OutStyle("notice", "This daemon process needs to stay alive for the mount to be accessible ...")
port, err := cmdUtil.GetPort() port, err := cmdUtil.GetPort()
if err != nil { if err != nil {
console.Fatal("Error finding port for mount: %v", err) exit.WithError("Error finding port for mount", err)
os.Exit(1)
} }
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
@ -128,8 +118,7 @@ var mountCmd = &cobra.Command{
}() }()
err = cluster.MountHost(api, ip, vmPath, port, mountVersion, uid, gid, msize) err = cluster.MountHost(api, ip, vmPath, port, mountVersion, uid, gid, msize)
if err != nil { if err != nil {
console.Fatal(err.Error()) exit.WithError("failed to mount host", err)
os.Exit(1)
} }
wg.Wait() wg.Wait()
}, },

View File

@ -37,6 +37,7 @@ import (
"k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm" "k8s.io/minikube/pkg/minikube/bootstrapper/kubeadm"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/notify" "k8s.io/minikube/pkg/minikube/notify"
) )
@ -70,7 +71,7 @@ var RootCmd = &cobra.Command{
PersistentPreRun: func(cmd *cobra.Command, args []string) { PersistentPreRun: func(cmd *cobra.Command, args []string) {
for _, path := range dirs { for _, path := range dirs {
if err := os.MkdirAll(path, 0777); err != nil { if err := os.MkdirAll(path, 0777); err != nil {
glog.Exitf("Error creating minikube directory: %v", err) exit.WithError("Error creating minikube directory", err)
} }
} }
@ -101,7 +102,8 @@ var RootCmd = &cobra.Command{
// This is called by main.main(). It only needs to happen once to the rootCmd. // This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() { func Execute() {
if err := RootCmd.Execute(); err != nil { if err := RootCmd.Execute(); err != nil {
os.Exit(1) // Cobra already outputs the error, typically because the user provided an unknown command.
os.Exit(exit.BadUsage)
} }
} }

View File

@ -17,13 +17,12 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"text/template" "text/template"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
) )
@ -48,8 +47,7 @@ var serviceCmd = &cobra.Command{
PersistentPreRun: func(cmd *cobra.Command, args []string) { PersistentPreRun: func(cmd *cobra.Command, args []string) {
t, err := template.New("serviceURL").Parse(serviceURLFormat) t, err := template.New("serviceURL").Parse(serviceURLFormat)
if err != nil { if err != nil {
console.Fatal("The value passed to --format is invalid: %v", err) exit.WithError("The value passed to --format is invalid", err)
os.Exit(1)
} }
serviceURLTemplate = t serviceURLTemplate = t
@ -57,15 +55,13 @@ var serviceCmd = &cobra.Command{
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 || len(args) > 1 { if len(args) == 0 || len(args) > 1 {
console.Fatal("No service name was specified.") exit.Usage("You must specify a service name")
os.Exit(1)
} }
svc := args[0] svc := args[0]
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
@ -73,8 +69,7 @@ var serviceCmd = &cobra.Command{
err = service.WaitAndMaybeOpenService(api, namespace, svc, err = service.WaitAndMaybeOpenService(api, namespace, svc,
serviceURLTemplate, serviceURLMode, https, wait, interval) serviceURLTemplate, serviceURLMode, https, wait, interval)
if err != nil { if err != nil {
console.Fatal("Error opening service: %v", err) exit.WithError("Error opening service", err)
os.Exit(1)
} }
}, },
} }

View File

@ -24,6 +24,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
) )
@ -38,15 +39,14 @@ var serviceListCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
serviceURLs, err := service.GetServiceURLs(api, serviceListNamespace, serviceURLTemplate) serviceURLs, err := service.GetServiceURLs(api, serviceListNamespace, serviceURLTemplate)
if err != nil { if err != nil {
console.Fatal("Failed to get service URL: %v", err) console.Fatal("Failed to get service URL: %v", err)
console.ErrStyle("notice", "Check that minikube is running and that you have specified the correct namespace (-n flag) if required.") console.ErrStyle("notice", "Check that minikube is running and that you have specified the correct namespace (-n flag) if required.")
os.Exit(1) os.Exit(exit.Unavailable)
} }
var data [][]string var data [][]string

View File

@ -17,12 +17,10 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
) )
@ -34,23 +32,19 @@ var sshCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName())
if err != nil { if err != nil {
console.Fatal("Error getting host: %v", err) exit.WithError("Error getting host", err)
os.Exit(1)
} }
if host.Driver.DriverName() == "none" { if host.Driver.DriverName() == "none" {
console.Fatal(`'none' driver does not support 'minikube ssh' command`) exit.Usage("'none' driver does not support 'minikube ssh' command")
os.Exit(1)
} }
err = cluster.CreateSSHShell(api, args) err = cluster.CreateSSHShell(api, args)
if err != nil { if err != nil {
console.Fatal("Error creating SSH shell: %v", err) exit.WithError("Error creating SSH shell", err)
os.Exit(1)
} }
}, },
} }

View File

@ -45,6 +45,7 @@ import (
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/cruntime"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
pkgutil "k8s.io/minikube/pkg/util" pkgutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/pkg/util/kubeconfig" "k8s.io/minikube/pkg/util/kubeconfig"
@ -157,12 +158,12 @@ func runStart(cmd *cobra.Command, args []string) {
oldConfig, err := cfg.Load() oldConfig, err := cfg.Load()
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
fatalExit("Unable to load config: %v", err) exit.WithCode(exit.Data, "Unable to load config: %v", err)
} }
kVersion := validateKubernetesVersions(oldConfig) kVersion := validateKubernetesVersions(oldConfig)
config, err := generateConfig(cmd, kVersion) config, err := generateConfig(cmd, kVersion)
if err != nil { if err != nil {
reportErrAndExit("Failed to generate config: %v", err) exit.WithError("Failed to generate config", err)
} }
var cacheGroup errgroup.Group var cacheGroup errgroup.Group
@ -171,12 +172,12 @@ func runStart(cmd *cobra.Command, args []string) {
// Abstraction leakage alert: startHost requires the config to be saved, to satistfy pkg/provision/buildroot. // Abstraction leakage alert: startHost requires the config to be saved, to satistfy pkg/provision/buildroot.
// Hence, saveConfig must be called before startHost, and again afterwards when we know the IP. // Hence, saveConfig must be called before startHost, and again afterwards when we know the IP.
if err := saveConfig(config); err != nil { if err := saveConfig(config); err != nil {
reportErrAndExit("Failed to save config", err) exit.WithError("Failed to save config", err)
} }
m, err := machine.NewAPIClient() m, err := machine.NewAPIClient()
if err != nil { if err != nil {
reportErrAndExit("Failed to get machine client: %v", err) exit.WithError("Failed to get machine client", err)
} }
host, preexisting := startHost(m, config.MachineConfig) host, preexisting := startHost(m, config.MachineConfig)
@ -184,7 +185,7 @@ func runStart(cmd *cobra.Command, args []string) {
// Save IP to configuration file for subsequent use // Save IP to configuration file for subsequent use
config.KubernetesConfig.NodeIP = ip config.KubernetesConfig.NodeIP = ip
if err := saveConfig(config); err != nil { if err := saveConfig(config); err != nil {
reportErrAndExit("Failed to save config", err) exit.WithError("Failed to save config", err)
} }
configureRuntimes(host) configureRuntimes(host)
@ -212,11 +213,11 @@ func runStart(cmd *cobra.Command, args []string) {
func validateConfig() { func validateConfig() {
diskSizeMB := pkgutil.CalculateDiskSizeInMB(viper.GetString(humanReadableDiskSize)) diskSizeMB := pkgutil.CalculateDiskSizeInMB(viper.GetString(humanReadableDiskSize))
if diskSizeMB < constants.MinimumDiskSizeMB { if diskSizeMB < constants.MinimumDiskSizeMB {
fatalExit("Requested disk size (%dMB) is less than minimum of %dMB", diskSizeMB, constants.MinimumDiskSizeMB) exit.WithCode(exit.Config, "Requested disk size (%dMB) is less than minimum of %dMB", diskSizeMB, constants.MinimumDiskSizeMB)
} }
if viper.GetBool(gpu) && viper.GetString(vmDriver) != "kvm2" { if viper.GetBool(gpu) && viper.GetString(vmDriver) != "kvm2" {
fatalExit("Sorry, the --gpu feature is currently only supported with --vm-driver=kvm2") exit.Usage("Sorry, the --gpu feature is currently only supported with --vm-driver=kvm2")
} }
} }
@ -316,7 +317,7 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_
} }
if err := pkgutil.MaybeChownDirRecursiveToMinikubeUser(constants.GetMinipath()); err != nil { if err := pkgutil.MaybeChownDirRecursiveToMinikubeUser(constants.GetMinipath()); err != nil {
fatalExit("Failed to chown %s: %v", constants.GetMinipath(), err) exit.WithCode(exit.Permissions, "Failed to chown %s: %v", constants.GetMinipath(), err)
} }
} }
@ -324,7 +325,7 @@ This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_
func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) { func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) {
exists, err := api.Exists(cfg.GetMachineName()) exists, err := api.Exists(cfg.GetMachineName())
if err != nil { if err != nil {
reportErrAndExit("Failed to check if machine exists", err) exit.WithError("Failed to check if machine exists", err)
} }
if mc.VMDriver == constants.DriverNone { if mc.VMDriver == constants.DriverNone {
console.OutStyle("starting-none", "Configuring local host environment ...") console.OutStyle("starting-none", "Configuring local host environment ...")
@ -346,7 +347,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) {
return err return err
} }
if err = pkgutil.RetryAfter(3, start, 2*time.Second); err != nil { if err = pkgutil.RetryAfter(3, start, 2*time.Second); err != nil {
reportErrAndExit("Unable to start VM", err) exit.WithError("Unable to start VM", err)
} }
return host, exists return host, exists
} }
@ -355,7 +356,7 @@ func startHost(api libmachine.API, mc cfg.MachineConfig) (*host.Host, bool) {
func validateNetwork(h *host.Host) string { func validateNetwork(h *host.Host) string {
ip, err := h.Driver.GetIP() ip, err := h.Driver.GetIP()
if err != nil { if err != nil {
reportErrAndExit("Unable to get VM IP address", err) exit.WithError("Unable to get VM IP address", err)
} }
console.OutStyle("connectivity", "%q IP address is %s", cfg.GetMachineName(), ip) console.OutStyle("connectivity", "%q IP address is %s", cfg.GetMachineName(), ip)
@ -382,7 +383,7 @@ func validateKubernetesVersions(old *cfg.Config) string {
} }
nvs, err := semver.Make(strings.TrimPrefix(nv, version.VersionPrefix)) nvs, err := semver.Make(strings.TrimPrefix(nv, version.VersionPrefix))
if err != nil { if err != nil {
fatalExit("Unable to parse %q: %v", nv, err) exit.WithCode(exit.Data, "Unable to parse %q: %v", nv, err)
} }
if old == nil || old.KubernetesConfig.KubernetesVersion == "" { if old == nil || old.KubernetesConfig.KubernetesVersion == "" {
@ -409,7 +410,7 @@ func validateKubernetesVersions(old *cfg.Config) string {
func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Bootstrapper { func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstrapper.Bootstrapper {
bs, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) bs, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper))
if err != nil { if err != nil {
reportErrAndExit("Failed to get bootstrapper", err) exit.WithError("Failed to get bootstrapper", err)
} }
console.OutStyle("copying", "Preparing Kubernetes environment ...") console.OutStyle("copying", "Preparing Kubernetes environment ...")
for _, eo := range extraOptions { for _, eo := range extraOptions {
@ -417,10 +418,10 @@ func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstr
} }
// Loads cached images, generates config files, download binaries // Loads cached images, generates config files, download binaries
if err := bs.UpdateCluster(kc); err != nil { if err := bs.UpdateCluster(kc); err != nil {
reportErrAndExit("Failed to update cluster", err) exit.WithError("Failed to update cluster", err)
} }
if err := bs.SetupCerts(kc); err != nil { if err := bs.SetupCerts(kc); err != nil {
reportErrAndExit("Failed to setup certs", err) exit.WithError("Failed to setup certs", err)
} }
return bs return bs
} }
@ -429,7 +430,7 @@ func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstr
func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup {
addr, err := h.Driver.GetURL() addr, err := h.Driver.GetURL()
if err != nil { if err != nil {
reportErrAndExit("Failed to get driver URL", err) exit.WithError("Failed to get driver URL", err)
} }
addr = strings.Replace(addr, "tcp://", "https://", -1) addr = strings.Replace(addr, "tcp://", "https://", -1)
addr = strings.Replace(addr, ":2376", ":"+strconv.Itoa(c.KubernetesConfig.NodePort), -1) addr = strings.Replace(addr, ":2376", ":"+strconv.Itoa(c.KubernetesConfig.NodePort), -1)
@ -445,7 +446,7 @@ func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup {
} }
kcs.SetKubeConfigFile(cmdutil.GetKubeConfigPath()) kcs.SetKubeConfigFile(cmdutil.GetKubeConfigPath())
if err := kubeconfig.SetupKubeConfig(kcs); err != nil { if err := kubeconfig.SetupKubeConfig(kcs); err != nil {
reportErrAndExit("Failed to setup kubeconfig", err) exit.WithError("Failed to setup kubeconfig", err)
} }
return kcs return kcs
} }
@ -454,14 +455,13 @@ func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup {
func configureRuntimes(h *host.Host) { func configureRuntimes(h *host.Host) {
runner, err := machine.CommandRunner(h) runner, err := machine.CommandRunner(h)
if err != nil { if err != nil {
reportErrAndExit("Failed to get command runner", err) exit.WithError("Failed to get command runner", err)
} }
config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner} config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner}
cr, err := cruntime.New(config) cr, err := cruntime.New(config)
if err != nil { if err != nil {
reportErrAndExit(fmt.Sprintf("Failed runtime for %+v", config), err) exit.WithError(fmt.Sprintf("Failed runtime for %+v", config), err)
cmdutil.MaybeReportErrorAndExit(err)
} }
console.OutStyle(cr.Name(), "Configuring %s as your container runtime ...", cr.Name()) console.OutStyle(cr.Name(), "Configuring %s as your container runtime ...", cr.Name())
for _, v := range dockerOpt { for _, v := range dockerOpt {
@ -473,7 +473,7 @@ func configureRuntimes(h *host.Host) {
err = cr.Enable() err = cr.Enable()
if err != nil { if err != nil {
cmdutil.MaybeReportErrorAndExit(err) exit.WithError("Failed to enable container runtime", err)
} }
} }
@ -493,7 +493,7 @@ func waitCacheImages(g *errgroup.Group) {
func bootstrapCluster(bs bootstrapper.Bootstrapper, kc cfg.KubernetesConfig, preexisting bool) { func bootstrapCluster(bs bootstrapper.Bootstrapper, kc cfg.KubernetesConfig, preexisting bool) {
console.OutStyle("pulling", "Pulling images used by Kubernetes %s ...", kc.KubernetesVersion) console.OutStyle("pulling", "Pulling images used by Kubernetes %s ...", kc.KubernetesVersion)
if err := bs.PullImages(kc); err != nil { if err := bs.PullImages(kc); err != nil {
fmt.Printf("Unable to pull images, which may be OK: %v", err) console.OutStyle("failure", "Unable to pull images, which may be OK: %v", err)
} }
// hum. bootstrapper.Bootstrapper should probably have a Name function. // hum. bootstrapper.Bootstrapper should probably have a Name function.
bsName := viper.GetString(cmdcfg.Bootstrapper) bsName := viper.GetString(cmdcfg.Bootstrapper)
@ -501,14 +501,14 @@ func bootstrapCluster(bs bootstrapper.Bootstrapper, kc cfg.KubernetesConfig, pre
if preexisting { if preexisting {
console.OutStyle("restarting", "Relaunching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName) console.OutStyle("restarting", "Relaunching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName)
if err := bs.RestartCluster(kc); err != nil { if err := bs.RestartCluster(kc); err != nil {
reportErrAndExit("Error restarting cluster", err) exit.WithError("Error restarting cluster", err)
} }
return return
} }
console.OutStyle("launch", "Launching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName) console.OutStyle("launch", "Launching Kubernetes %s using %s ... ", kc.KubernetesVersion, bsName)
if err := bs.StartCluster(kc); err != nil { if err := bs.StartCluster(kc); err != nil {
reportErrAndExit("Error starting cluster", err) exit.WithError("Error starting cluster", err)
} }
} }
@ -525,7 +525,7 @@ func validateCluster(bs bootstrapper.Bootstrapper, ip string) {
} }
err := pkgutil.RetryAfter(20, kStat, 3*time.Second) err := pkgutil.RetryAfter(20, kStat, 3*time.Second)
if err != nil { if err != nil {
reportErrAndExit("kubelet checks failed", err) exit.WithError("kubelet checks failed", err)
} }
aStat := func() (err error) { aStat := func() (err error) {
st, err := bs.GetApiServerStatus(net.ParseIP(ip)) st, err := bs.GetApiServerStatus(net.ParseIP(ip))
@ -538,7 +538,7 @@ func validateCluster(bs bootstrapper.Bootstrapper, ip string) {
err = pkgutil.RetryAfter(30, aStat, 10*time.Second) err = pkgutil.RetryAfter(30, aStat, 10*time.Second)
if err != nil { if err != nil {
reportErrAndExit("apiserver checks failed", err) exit.WithError("apiserver checks failed", err)
} }
console.OutLn("") console.OutLn("")
} }
@ -562,12 +562,10 @@ func configureMounts() {
mountCmd.Stderr = os.Stderr mountCmd.Stderr = os.Stderr
} }
if err := mountCmd.Start(); err != nil { if err := mountCmd.Start(); err != nil {
glog.Errorf("Error running command minikube mount %v", err) exit.WithError("Error starting mount", err)
cmdutil.MaybeReportErrorAndExit(err)
} }
if err := ioutil.WriteFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName), []byte(strconv.Itoa(mountCmd.Process.Pid)), 0644); err != nil { if err := ioutil.WriteFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName), []byte(strconv.Itoa(mountCmd.Process.Pid)), 0644); err != nil {
glog.Errorf("Error writing mount process pid to file: %v", err) exit.WithError("Error writing mount pid", err)
cmdutil.MaybeReportErrorAndExit(err)
} }
} }
@ -614,18 +612,3 @@ func saveConfig(clusterConfig cfg.Config) error {
} }
return nil return nil
} }
// fatalExit is a shortcut for outputting a failure message and exiting.
func fatalExit(format string, a ...interface{}) {
// use Warning because Error will display a duplicate message
glog.Warningf(format, a...)
console.Fatal(format, a...)
os.Exit(1)
}
// reportFatalExit is a shortcut for outputting an error, reporting it, and exiting.
func reportErrAndExit(msg string, err error) {
console.Fatal(msg+": %v", err)
cmdutil.MaybeReportErrorAndExit(err)
os.Exit(1)
}

View File

@ -25,11 +25,11 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config"
cmdUtil "k8s.io/minikube/cmd/util" "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/util/kubeconfig" "k8s.io/minikube/pkg/util/kubeconfig"
) )
@ -43,8 +43,6 @@ type Status struct {
Kubeconfig string Kubeconfig string
} }
const internalErrorCode = -1
const ( const (
minikubeNotRunningStatusFlag = 1 << 0 minikubeNotRunningStatusFlag = 1 << 0
clusterNotRunningStatusFlag = 1 << 1 clusterNotRunningStatusFlag = 1 << 1
@ -62,15 +60,13 @@ var statusCmd = &cobra.Command{
var returnCode = 0 var returnCode = 0
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithCode(exit.Unavailable, "Error getting client: %v", err)
os.Exit(internalErrorCode)
} }
defer api.Close() defer api.Close()
hostSt, err := cluster.GetHostStatus(api) hostSt, err := cluster.GetHostStatus(api)
if err != nil { if err != nil {
glog.Errorln("Error getting machine status:", err) exit.WithError("Error getting host status", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode)
} }
kubeletSt := state.None.String() kubeletSt := state.None.String()
@ -80,13 +76,12 @@ var statusCmd = &cobra.Command{
if hostSt == state.Running.String() { if hostSt == state.Running.String() {
clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper)) clusterBootstrapper, err := GetClusterBootstrapper(api, viper.GetString(cmdcfg.Bootstrapper))
if err != nil { if err != nil {
glog.Errorf("Error getting cluster bootstrapper: %v", err) exit.WithError("Error getting bootstrapper", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode)
} }
kubeletSt, err = clusterBootstrapper.GetKubeletStatus() kubeletSt, err = clusterBootstrapper.GetKubeletStatus()
if err != nil { if err != nil {
glog.Errorln("Error kubelet status:", err) glog.Warningf("kubelet err: %v", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode) returnCode |= clusterNotRunningStatusFlag
} else if kubeletSt != state.Running.String() { } else if kubeletSt != state.Running.String() {
returnCode |= clusterNotRunningStatusFlag returnCode |= clusterNotRunningStatusFlag
} }
@ -94,21 +89,18 @@ var statusCmd = &cobra.Command{
ip, err := cluster.GetHostDriverIP(api, config.GetMachineName()) ip, err := cluster.GetHostDriverIP(api, config.GetMachineName())
if err != nil { if err != nil {
glog.Errorln("Error host driver ip status:", err) glog.Errorln("Error host driver ip status:", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode)
} }
apiserverSt, err = clusterBootstrapper.GetApiServerStatus(ip) apiserverSt, err = clusterBootstrapper.GetApiServerStatus(ip)
if err != nil { if err != nil {
glog.Errorln("Error apiserver status:", err) glog.Errorln("Error apiserver status:", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode)
} else if apiserverSt != state.Running.String() { } else if apiserverSt != state.Running.String() {
returnCode |= clusterNotRunningStatusFlag returnCode |= clusterNotRunningStatusFlag
} }
ks, err := kubeconfig.GetKubeConfigStatus(ip, cmdUtil.GetKubeConfigPath(), config.GetMachineName()) ks, err := kubeconfig.GetKubeConfigStatus(ip, util.GetKubeConfigPath(), config.GetMachineName())
if err != nil { if err != nil {
glog.Errorln("Error kubeconfig status:", err) glog.Errorln("Error kubeconfig status:", err)
cmdUtil.MaybeReportErrorAndExitWithCode(err, internalErrorCode)
} }
if ks { if ks {
kubeconfigSt = "Correctly Configured: pointing to minikube-vm at " + ip.String() kubeconfigSt = "Correctly Configured: pointing to minikube-vm at " + ip.String()
@ -129,13 +121,11 @@ var statusCmd = &cobra.Command{
} }
tmpl, err := template.New("status").Parse(statusFormat) tmpl, err := template.New("status").Parse(statusFormat)
if err != nil { if err != nil {
glog.Errorln("Error creating status template:", err) exit.WithError("Error creating status template", err)
os.Exit(internalErrorCode)
} }
err = tmpl.Execute(os.Stdout, status) err = tmpl.Execute(os.Stdout, status)
if err != nil { if err != nil {
glog.Errorln("Error executing status template:", err) exit.WithError("Error executing status template", err)
os.Exit(internalErrorCode)
} }
os.Exit(returnCode) os.Exit(returnCode)

View File

@ -17,7 +17,6 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"time" "time"
"github.com/docker/machine/libmachine/mcnerror" "github.com/docker/machine/libmachine/mcnerror"
@ -28,6 +27,7 @@ import (
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
pkg_config "k8s.io/minikube/pkg/minikube/config" pkg_config "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
pkgutil "k8s.io/minikube/pkg/util" pkgutil "k8s.io/minikube/pkg/util"
) )
@ -44,8 +44,7 @@ itself, leaving all files intact. The cluster can be started again with the "sta
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
@ -63,15 +62,14 @@ itself, leaving all files intact. The cluster can be started again with the "sta
} }
} }
if err := pkgutil.RetryAfter(5, stop, 1*time.Second); err != nil { if err := pkgutil.RetryAfter(5, stop, 1*time.Second); err != nil {
console.Fatal("Unable to stop VM: %v", err) exit.WithError("Unable to stop VM", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
if !nonexistent { if !nonexistent {
console.OutStyle("stopped", "%q stopped.", profile) console.OutStyle("stopped", "%q stopped.", profile)
} }
if err := cmdUtil.KillMountProcess(); err != nil { if err := cmdUtil.KillMountProcess(); err != nil {
console.Fatal("Unable to kill mount process: %v", err) exit.WithError("Unable to kill mount process", err)
} }
}, },
} }

View File

@ -20,14 +20,15 @@ import (
"context" "context"
"os" "os"
"os/signal" "os/signal"
"time"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/service"
"k8s.io/minikube/pkg/minikube/tunnel" "k8s.io/minikube/pkg/minikube/tunnel"
"time"
) )
var cleanup bool var cleanup bool
@ -54,7 +55,7 @@ var tunnelCmd = &cobra.Command{
glog.Infof("Creating docker machine client...") glog.Infof("Creating docker machine client...")
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
glog.Fatalf("error creating dockermachine client: %s", err) exit.WithError("error creating machine client", err)
} }
glog.Infof("Creating k8s client...") glog.Infof("Creating k8s client...")
@ -64,7 +65,7 @@ var tunnelCmd = &cobra.Command{
//doesn't hang on the API server call during startup and shutdown time or if there is a temporary error. //doesn't hang on the API server call during startup and shutdown time or if there is a temporary error.
clientset, err := service.K8s.GetClientset(1 * time.Second) clientset, err := service.K8s.GetClientset(1 * time.Second)
if err != nil { if err != nil {
glog.Fatalf("error creating K8S clientset: %s", err) exit.WithError("error creating clientset", err)
} }
ctrlC := make(chan os.Signal, 1) ctrlC := make(chan os.Signal, 1)
@ -77,7 +78,7 @@ var tunnelCmd = &cobra.Command{
done, err := manager.StartTunnel(ctx, config.GetMachineName(), api, config.DefaultLoader, clientset.CoreV1()) done, err := manager.StartTunnel(ctx, config.GetMachineName(), api, config.DefaultLoader, clientset.CoreV1())
if err != nil { if err != nil {
glog.Fatalf("error starting tunnel: %s", err) exit.WithError("error starting tunnel", err)
} }
<-done <-done
}, },

View File

@ -17,11 +17,10 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/notify" "k8s.io/minikube/pkg/minikube/notify"
"k8s.io/minikube/pkg/version" "k8s.io/minikube/pkg/version"
) )
@ -38,13 +37,11 @@ var updateCheckCmd = &cobra.Command{
url := constants.GithubMinikubeReleasesURL url := constants.GithubMinikubeReleasesURL
r, err := notify.GetAllVersionsFromURL(url) r, err := notify.GetAllVersionsFromURL(url)
if err != nil { if err != nil {
console.Fatal("Unable to fetch latest version info: %v", err) exit.WithError("Unable to fetch latest version info", err)
os.Exit(1)
} }
if len(r) < 1 { if len(r) < 1 {
console.Fatal("Update server returned an empty list") exit.WithCode(exit.Data, "Update server returned an empty list")
os.Exit(2)
} }
console.OutLn("CurrentVersion: %s", version.GetVersion()) console.OutLn("CurrentVersion: %s", version.GetVersion())

View File

@ -17,15 +17,12 @@ limitations under the License.
package cmd package cmd
import ( import (
"os"
"github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdUtil "k8s.io/minikube/cmd/util"
"k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/machine"
kcfg "k8s.io/minikube/pkg/util/kubeconfig" kcfg "k8s.io/minikube/pkg/util/kubeconfig"
) )
@ -39,20 +36,17 @@ var updateContextCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
api, err := machine.NewAPIClient() api, err := machine.NewAPIClient()
if err != nil { if err != nil {
console.Fatal("Error getting client: %v", err) exit.WithError("Error getting client", err)
os.Exit(1)
} }
defer api.Close() defer api.Close()
machineName := config.GetMachineName() machineName := config.GetMachineName()
ip, err := cluster.GetHostDriverIP(api, machineName) ip, err := cluster.GetHostDriverIP(api, machineName)
if err != nil { if err != nil {
glog.Errorln("Error host driver ip status:", err) exit.WithError("Error host driver ip status", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
updated, err := kcfg.UpdateKubeconfigIP(ip, constants.KubeconfigPath, machineName) updated, err := kcfg.UpdateKubeconfigIP(ip, constants.KubeconfigPath, machineName)
if err != nil { if err != nil {
glog.Errorln("Error kubeconfig status:", err) exit.WithError("update config", err)
cmdUtil.MaybeReportErrorAndExit(err)
} }
if updated { if updated {
console.OutStyle("celebrate", "IP has been updated to point at %s", ip) console.OutStyle("celebrate", "IP has been updated to point at %s", ip)

View File

@ -14,34 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// package util is a hodge-podge of utility functions that should be moved elsewhere.
package util package util
import ( import (
"bufio"
"bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net" "net"
"net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"time"
"github.com/golang/glog"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
"golang.org/x/crypto/ssh/terminal"
minikubeConfig "k8s.io/minikube/cmd/minikube/cmd/config"
"k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/version"
) )
type ServiceContext struct { type ServiceContext struct {
@ -49,11 +39,6 @@ type ServiceContext struct {
Version string `json:"version"` Version string `json:"version"`
} }
type Message struct {
Message string `json:"message"`
ServiceContext `json:"serviceContext"`
}
type LookPath func(filename string) (string, error) type LookPath func(filename string) (string, error)
var lookPath LookPath var lookPath LookPath
@ -62,145 +47,6 @@ func init() {
lookPath = exec.LookPath lookPath = exec.LookPath
} }
func ReportError(err error, url string) error {
errMsg, err := FormatError(err)
if err != nil {
return errors.Wrap(err, "Error formatting error message")
}
jsonErrorMsg, err := MarshallError(errMsg, "default", version.GetVersion())
if err != nil {
return errors.Wrap(err, "Error marshalling error message to JSON")
}
err = UploadError(jsonErrorMsg, url)
if err != nil {
return errors.Wrap(err, "Error uploading error message")
}
return nil
}
func FormatError(err error) (string, error) {
if err == nil {
return "", errors.New("Error: ReportError was called with nil error value")
}
type stackTracer interface {
StackTrace() errors.StackTrace
}
errOutput := []string{}
errOutput = append(errOutput, err.Error())
if err, ok := err.(stackTracer); ok {
for _, f := range err.StackTrace() {
errOutput = append(errOutput, fmt.Sprintf("\tat %n(%v)", f, f))
}
} else {
return "", errors.New("Error msg with no stack trace cannot be reported")
}
return strings.Join(errOutput, "\n"), nil
}
func MarshallError(errMsg, service, version string) ([]byte, error) {
m := Message{errMsg, ServiceContext{service, version}}
b, err := json.Marshal(m)
if err != nil {
return nil, errors.Wrap(err, "")
}
return b, nil
}
func UploadError(b []byte, url string) error {
req, err := http.NewRequest("POST", url, bytes.NewBuffer(b))
if err != nil {
return errors.Wrap(err, "")
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return errors.Wrap(err, "")
} else if resp.StatusCode != 200 {
return errors.Errorf("Error sending error report to %s, got response code %d", url, resp.StatusCode)
}
return nil
}
func MaybeReportErrorAndExit(errToReport error) {
MaybeReportErrorAndExitWithCode(errToReport, 1)
}
// MaybeReportErrorAndExitWithCode prompts the user if they would like to report a stack trace, and exits.
func MaybeReportErrorAndExitWithCode(errToReport error, returnCode int) {
// TODO(#3623,3178): Replace with maybeReportErrorAndExitWithCode once StackDriver integration is improved.
glog.Infof("Error reporting is disabled in this release of minikube")
os.Exit(returnCode)
}
// maybeReportErrorAndExitWithCode is deadcode
func maybeReportErrorAndExitWithCode(errToReport error, returnCode int) {
var err error
if viper.GetBool(config.WantReportError) {
err = ReportError(errToReport, constants.ReportingURL)
} else if viper.GetBool(config.WantReportErrorPrompt) {
console.Err(
`================================================================================
An error has occurred. Would you like to opt in to sending anonymized crash
information to minikube to help prevent future errors?
To disable this prompt, run: 'minikube config set WantReportErrorPrompt false'
================================================================================`)
if PromptUserForAccept(os.Stdin) {
err = minikubeConfig.Set(config.WantReportError, "true")
if err == nil {
err = ReportError(errToReport, constants.ReportingURL)
}
} else {
console.ErrStyle("meh", "Bummer, perhaps next time!")
}
}
// This happens when the error was created without errors.Wrap(), and thus has no trace data.
if err != nil {
glog.Infof("report error failed: %v", err)
}
os.Exit(returnCode)
}
func getInput(input chan string, r io.Reader) {
reader := bufio.NewReader(r)
console.OutLn("Please enter your response [Y/n]: ")
response, err := reader.ReadString('\n')
if err != nil {
glog.Errorf(err.Error())
}
input <- response
}
func PromptUserForAccept(r io.Reader) bool {
if !terminal.IsTerminal(int(os.Stdout.Fd())) {
return false
}
input := make(chan string, 1)
go getInput(input, r)
select {
case response := <-input:
response = strings.ToLower(strings.TrimSpace(response))
if response == "y" || response == "yes" || response == "" {
return true
} else if response == "n" || response == "no" {
return false
} else {
console.Warning("Invalid response, error reporting remains disabled. Must be in form [Y/n]")
return false
}
case <-time.After(30 * time.Second):
console.Warning("Prompt timed out.")
return false
}
}
func MaybePrintKubectlDownloadMsg(goos string, out io.Writer) { func MaybePrintKubectlDownloadMsg(goos string, out io.Writer) {
if !viper.GetBool(config.WantKubectlDownloadMsg) { if !viper.GetBool(config.WantKubectlDownloadMsg) {
return return

View File

@ -19,18 +19,16 @@ package util
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"k8s.io/client-go/tools/clientcmd"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
"strings" "strings"
"testing" "testing"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/version"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/minikube/pkg/minikube/config"
) )
func startTestHTTPServer(returnError bool, response string) *httptest.Server { func startTestHTTPServer(returnError bool, response string) *httptest.Server {
@ -43,65 +41,6 @@ func startTestHTTPServer(returnError bool, response string) *httptest.Server {
})) }))
} }
func TestFormatError(t *testing.T) {
var testErr error
if _, err := FormatError(testErr); err == nil {
t.Fatalf("FormatError should have errored with a nil error input")
}
testErr = fmt.Errorf("Not a valid error to format as there is no stacktrace")
if out, err := FormatError(testErr); err == nil {
t.Fatalf("FormatError should have errored with a non pkg/errors error (no stacktrace info): %s", out)
}
testErr = errors.New("TestFormatError 1")
errors.Wrap(testErr, "TestFormatError 2")
errors.Wrap(testErr, "TestFormatError 3")
_, err := FormatError(testErr)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}
func TestMarshallError(t *testing.T) {
testErr := errors.New("TestMarshallError 1")
errors.Wrap(testErr, "TestMarshallError 2")
errors.Wrap(testErr, "TestMarshallError 3")
errMsg, _ := FormatError(testErr)
if _, err := MarshallError(errMsg, "default", version.GetVersion()); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}
func TestUploadError(t *testing.T) {
testErr := errors.New("TestUploadError 1")
errors.Wrap(testErr, "TestUploadError 2")
errors.Wrap(testErr, "TestUploadError 3")
errMsg, _ := FormatError(testErr)
jsonErrMsg, _ := MarshallError(errMsg, "default", version.GetVersion())
server := startTestHTTPServer(false, "http test")
if err := UploadError(jsonErrMsg, server.URL); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
server = startTestHTTPServer(true, "failed to write report")
if err := UploadError(jsonErrMsg, server.URL); err == nil {
t.Fatalf("UploadError should have errored from a 400 response")
}
}
func TestReportError(t *testing.T) {
testErr := errors.New("TestError 1")
server := startTestHTTPServer(false, "http test")
if err := ReportError(testErr, server.URL); err != nil {
t.Fatalf("ReportError")
}
}
func revertLookPath(l LookPath) { func revertLookPath(l LookPath) {
lookPath = l lookPath = l
} }

View File

@ -25,9 +25,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/net"
pkgdrivers "k8s.io/minikube/pkg/drivers" // TODO(tstromberg): Extract CommandRunner into its own package
pkgdrivers "k8s.io/minikube/pkg/drivers"
// TODO(tstromberg): Extract CommandRunner into its own package
"k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/cruntime"
) )

View File

@ -23,7 +23,6 @@ import (
"fmt" "fmt"
"html/template" "html/template"
"net" "net"
"os"
"os/exec" "os/exec"
"regexp" "regexp"
"time" "time"
@ -41,6 +40,7 @@ import (
cfg "k8s.io/minikube/pkg/minikube/config" cfg "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/console" "k8s.io/minikube/pkg/minikube/console"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/registry" "k8s.io/minikube/pkg/minikube/registry"
"k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util"
pkgutil "k8s.io/minikube/pkg/util" pkgutil "k8s.io/minikube/pkg/util"
@ -243,9 +243,9 @@ func createHost(api libmachine.API, config cfg.MachineConfig) (*host.Host, error
def, err := registry.Driver(config.VMDriver) def, err := registry.Driver(config.VMDriver)
if err != nil { if err != nil {
if err == registry.ErrDriverNotFound { if err == registry.ErrDriverNotFound {
glog.Exitf("Unsupported driver: %s\n", config.VMDriver) exit.Usage("unsupported driver: %s", config.VMDriver)
} else { } else {
glog.Exit(err.Error()) exit.WithError("error getting driver", err)
} }
} }
@ -422,12 +422,10 @@ func CreateSSHShell(api libmachine.API, args []string) error {
func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) { func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) {
s, err := GetHostStatus(api) s, err := GetHostStatus(api)
if err != nil { if err != nil {
console.Fatal("Error getting machine status:", err) exit.WithError("Error getting machine status", err)
os.Exit(1)
} }
if s != state.Running.String() { if s != state.Running.String() {
console.ErrStyle("conflict", "minikube is not running, so the service cannot be accessed") exit.WithCode(exit.Unavailable, "minikube is not running, so the service cannot be accessed")
os.Exit(exitStatus)
} }
} }

View File

@ -47,8 +47,10 @@ var styles = map[string]style{
"waiting": {Prefix: "⌛ "}, "waiting": {Prefix: "⌛ "},
"usage": {Prefix: "💡 "}, "usage": {Prefix: "💡 "},
"launch": {Prefix: "🚀 "}, "launch": {Prefix: "🚀 "},
"sad": {Prefix: "😿 "},
"thumbs-up": {Prefix: "👍 "}, "thumbs-up": {Prefix: "👍 "},
"option": {Prefix: " ▪ "}, // Indented bullet "option": {Prefix: " ▪ "}, // Indented bullet
"url": {Prefix: "👉 "},
"crushed": {Prefix: "💔 "}, "crushed": {Prefix: "💔 "},
// Specialized purpose styles // Specialized purpose styles

View File

@ -39,10 +39,10 @@ import (
"github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/state"
"github.com/docker/machine/libmachine/swarm" "github.com/docker/machine/libmachine/swarm"
"github.com/docker/machine/libmachine/version" "github.com/docker/machine/libmachine/version"
"github.com/golang/glog"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/bootstrapper"
"k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/registry" "k8s.io/minikube/pkg/minikube/registry"
"k8s.io/minikube/pkg/minikube/sshutil" "k8s.io/minikube/pkg/minikube/sshutil"
"k8s.io/minikube/pkg/provision" "k8s.io/minikube/pkg/provision"
@ -259,9 +259,10 @@ func (cg *CertGenerator) ValidateCertificate(addr string, authOptions *auth.Opti
func registerDriver(driverName string) { func registerDriver(driverName string) {
def, err := registry.Driver(driverName) def, err := registry.Driver(driverName)
if err != nil { if err == registry.ErrDriverNotFound {
glog.Exitf("Unsupported driver: %s\n", driverName) exit.Usage("unsupported driver: %s", driverName)
} else {
exit.WithError("error getting driver", err)
} }
plugin.RegisterDriver(def.DriverCreator()) plugin.RegisterDriver(def.DriverCreator())
} }