diff --git a/Makefile b/Makefile index 09c347ae91e1..02f4dbef7750 100755 --- a/Makefile +++ b/Makefile @@ -236,6 +236,16 @@ gendocs: out/docs/minikube.md fmt: @gofmt -l -s -w $(SOURCE_DIRS) +.PHONY: lint +lint: + @golint $(MINIKUBE_TEST_FILES) + +.PHONY: reportcard +reportcard: + goreportcard-cli -v + # "disabling misspell on large repo..." + -misspell -error $(SOURCE_DIRS) + .PHONY: mdlint mdlint: @$(MARKDOWNLINT) $(MINIKUBE_MARKDOWN_FILES) diff --git a/cmd/drivers/hyperkit/main.go b/cmd/drivers/hyperkit/main.go index 010770af7df8..5089b6e9ec28 100644 --- a/cmd/drivers/hyperkit/main.go +++ b/cmd/drivers/hyperkit/main.go @@ -1,3 +1,5 @@ +// +build darwin + /* Copyright 2016 The Kubernetes Authors All rights reserved. diff --git a/cmd/minikube/cmd/cache_list.go b/cmd/minikube/cmd/cache_list.go index a181af1f18d1..f3ce5de62ab9 100644 --- a/cmd/minikube/cmd/cache_list.go +++ b/cmd/minikube/cmd/cache_list.go @@ -28,6 +28,7 @@ import ( var cacheListFormat string +// CacheListTemplate represents the cache list template type CacheListTemplate struct { CacheImage string } diff --git a/cmd/minikube/cmd/completion.go b/cmd/minikube/cmd/completion.go index 14b10e74ae5e..7de31f908697 100644 --- a/cmd/minikube/cmd/completion.go +++ b/cmd/minikube/cmd/completion.go @@ -88,6 +88,7 @@ var completionCmd = &cobra.Command{ }, } +// GenerateBashCompletion generates the completion for the bash shell func GenerateBashCompletion(w io.Writer, cmd *cobra.Command) error { _, err := w.Write([]byte(boilerPlate)) if err != nil { @@ -102,8 +103,9 @@ func GenerateBashCompletion(w io.Writer, cmd *cobra.Command) error { return nil } +// GenerateZshCompletion generates the completion for the zsh shell func GenerateZshCompletion(out io.Writer, cmd *cobra.Command) error { - zsh_initialization := `#compdef minikube + zshInitialization := `#compdef minikube __minikube_bash_source() { alias shopt=':' @@ -242,7 +244,7 @@ __minikube_convert_bash_to_zsh() { return err } - _, err = out.Write([]byte(zsh_initialization)) + _, err = out.Write([]byte(zshInitialization)) if err != nil { return err } @@ -257,12 +259,12 @@ __minikube_convert_bash_to_zsh() { return err } - zsh_tail := ` + zshTail := ` BASH_COMPLETION_EOF } __minikube_bash_source <(__minikube_convert_bash_to_zsh) ` - _, err = out.Write([]byte(zsh_tail)) + _, err = out.Write([]byte(zshTail)) if err != nil { return err } diff --git a/cmd/minikube/cmd/config/addons.go b/cmd/minikube/cmd/config/addons.go index db1cdc189bf4..127a01149cf1 100644 --- a/cmd/minikube/cmd/config/addons.go +++ b/cmd/minikube/cmd/config/addons.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" ) +// AddonsCmd represents the addons command var AddonsCmd = &cobra.Command{ Use: "addons SUBCOMMAND [flags]", Short: "Modify minikube's kubernetes addons", diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index 00374dfe7573..483a543c948d 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -29,6 +29,7 @@ import ( var addonListFormat string +// AddonListTemplate represents the addon list template type AddonListTemplate struct { AddonName string AddonStatus string diff --git a/cmd/minikube/cmd/config/config.go b/cmd/minikube/cmd/config/config.go index b48163818a8d..c0fc8a49172f 100644 --- a/cmd/minikube/cmd/config/config.go +++ b/cmd/minikube/cmd/config/config.go @@ -28,10 +28,12 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) +// Bootstrapper is the name for bootstrapper const Bootstrapper = "bootstrapper" type setFn func(string, string) error +// Setting represents a setting type Setting struct { name string set func(config.MinikubeConfig, string, string) error @@ -49,6 +51,11 @@ var settings = []Setting{ validations: []setFn{IsValidDriver}, callbacks: []setFn{RequiresRestartMsg}, }, + { + name: "feature-gates", + set: SetString, + callbacks: []setFn{RequiresRestartMsg}, + }, { name: "v", set: SetInt, @@ -247,6 +254,7 @@ var settings = []Setting{ }, } +// ConfigCmd represents the config command var ConfigCmd = &cobra.Command{ Use: "config SUBCOMMAND [flags]", Short: "Modify minikube config", diff --git a/cmd/minikube/cmd/config/get.go b/cmd/minikube/cmd/config/get.go index 263d10fd9cca..704a1146f3e0 100644 --- a/cmd/minikube/cmd/config/get.go +++ b/cmd/minikube/cmd/config/get.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/spf13/cobra" - "k8s.io/minikube/pkg/minikube/config" + pkgConfig "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/console" ) @@ -36,7 +36,7 @@ var configGetCmd = &cobra.Command{ } cmd.SilenceUsage = true - val, err := config.Get(args[0]) + val, err := Get(args[0]) if err != nil { return err } @@ -52,3 +52,8 @@ var configGetCmd = &cobra.Command{ func init() { ConfigCmd.AddCommand(configGetCmd) } + +// Get gets a property +func Get(name string) (string, error) { + return pkgConfig.Get(name) +} diff --git a/cmd/minikube/cmd/config/profile.go b/cmd/minikube/cmd/config/profile.go index 7d91e5f6c954..a3427f0513c6 100644 --- a/cmd/minikube/cmd/config/profile.go +++ b/cmd/minikube/cmd/config/profile.go @@ -23,6 +23,7 @@ import ( "k8s.io/minikube/pkg/minikube/exit" ) +// ProfileCmd represents the profile command var ProfileCmd = &cobra.Command{ Use: "profile MINIKUBE_PROFILE_NAME. You can return to the default minikube profile by running `minikube profile default`", Short: "Profile sets the current minikube profile", diff --git a/cmd/minikube/cmd/config/prompt.go b/cmd/minikube/cmd/config/prompt.go index 8c181966b9df..499509a06a07 100644 --- a/cmd/minikube/cmd/config/prompt.go +++ b/cmd/minikube/cmd/config/prompt.go @@ -118,6 +118,7 @@ func concealableAskForStaticValue(readWriter io.ReadWriter, promptString string, } } +// AskForPasswordValue asks for a password value, while hiding the input func AskForPasswordValue(s string) string { stdInFd := int(os.Stdin.Fd()) diff --git a/cmd/minikube/cmd/config/set.go b/cmd/minikube/cmd/config/set.go index aa0b20b8d7ad..3982a8e32103 100644 --- a/cmd/minikube/cmd/config/set.go +++ b/cmd/minikube/cmd/config/set.go @@ -42,6 +42,7 @@ func init() { ConfigCmd.AddCommand(configSetCmd) } +// Set sets a property to a value func Set(name string, value string) error { s, err := findSetting(name) if err != nil { diff --git a/cmd/minikube/cmd/config/util.go b/cmd/minikube/cmd/config/util.go index e7201f8d8427..586981df1e34 100644 --- a/cmd/minikube/cmd/config/util.go +++ b/cmd/minikube/cmd/config/util.go @@ -56,16 +56,19 @@ func findSetting(name string) (Setting, error) { // Set Functions +// SetString sets a string value func SetString(m config.MinikubeConfig, name string, val string) error { m[name] = val return nil } +// SetMap sets a map value func SetMap(m config.MinikubeConfig, name string, val map[string]interface{}) error { m[name] = val return nil } +// SetConfigMap sets a config map value func SetConfigMap(m config.MinikubeConfig, name string, val string) error { list := strings.Split(val, ",") v := make(map[string]interface{}) @@ -76,6 +79,7 @@ func SetConfigMap(m config.MinikubeConfig, name string, val string) error { return nil } +// SetInt sets an int value func SetInt(m config.MinikubeConfig, name string, val string) error { i, err := strconv.Atoi(val) if err != nil { @@ -85,6 +89,7 @@ func SetInt(m config.MinikubeConfig, name string, val string) error { return nil } +// SetBool sets a bool value func SetBool(m config.MinikubeConfig, name string, val string) error { b, err := strconv.ParseBool(val) if err != nil { @@ -134,6 +139,7 @@ func EnableOrDisableAddon(name string, val string) error { return nil } +// EnableOrDisableStorageClasses enables or disables storage classes func EnableOrDisableStorageClasses(name, val string) error { enable, err := strconv.ParseBool(val) if err != nil { diff --git a/cmd/minikube/cmd/config/validations.go b/cmd/minikube/cmd/config/validations.go index 6170441256c0..3460a59296dc 100644 --- a/cmd/minikube/cmd/config/validations.go +++ b/cmd/minikube/cmd/config/validations.go @@ -33,6 +33,7 @@ import ( "k8s.io/minikube/pkg/minikube/cruntime" ) +// IsValidDriver checks if a driver is supported func IsValidDriver(string, driver string) error { for _, d := range constants.SupportedVMDrivers { if driver == d { @@ -42,11 +43,13 @@ func IsValidDriver(string, driver string) error { return fmt.Errorf("Driver %s is not supported", driver) } +// RequiresRestartMsg returns the "requires restart" message func RequiresRestartMsg(string, string) error { console.OutStyle("warning", "These changes will take effect upon a minikube delete and then a minikube start") return nil } +// IsValidDiskSize checks if a string is a valid disk size func IsValidDiskSize(name string, disksize string) error { _, err := units.FromHumanSize(disksize) if err != nil { @@ -55,6 +58,7 @@ func IsValidDiskSize(name string, disksize string) error { return nil } +// IsValidURL checks if a location is a valid URL func IsValidURL(name string, location string) error { _, err := url.Parse(location) if err != nil { @@ -63,6 +67,7 @@ func IsValidURL(name string, location string) error { return nil } +// IsURLExists checks if a location actually exists func IsURLExists(name string, location string) error { parsed, err := url.Parse(location) if err != nil { @@ -96,6 +101,7 @@ func IsURLExists(name string, location string) error { return nil } +// IsPositive checks if an integer is positive func IsPositive(name string, val string) error { i, err := strconv.Atoi(val) if err != nil { @@ -107,6 +113,7 @@ func IsPositive(name string, val string) error { return nil } +// IsValidCIDR checks if a string parses as a CIDR func IsValidCIDR(name string, cidr string) error { _, _, err := net.ParseCIDR(cidr) if err != nil { @@ -115,6 +122,7 @@ func IsValidCIDR(name string, cidr string) error { return nil } +// IsValidPath checks if a string is a valid path func IsValidPath(name string, path string) error { _, err := os.Stat(path) if err != nil { @@ -123,6 +131,7 @@ func IsValidPath(name string, path string) error { return nil } +// IsValidAddon checks if a string is a valid addon func IsValidAddon(name string, val string) error { if _, ok := assets.Addons[name]; ok { return nil diff --git a/cmd/minikube/cmd/config/config_view.go b/cmd/minikube/cmd/config/view.go similarity index 84% rename from cmd/minikube/cmd/config/config_view.go rename to cmd/minikube/cmd/config/view.go index 013bd26fc596..3ea025e92251 100644 --- a/cmd/minikube/cmd/config/config_view.go +++ b/cmd/minikube/cmd/config/view.go @@ -26,9 +26,10 @@ import ( "k8s.io/minikube/pkg/minikube/exit" ) -var configViewFormat string +var viewFormat string -type ConfigViewTemplate struct { +// ViewTemplate represents the view template +type ViewTemplate struct { ConfigKey string ConfigValue interface{} } @@ -38,7 +39,7 @@ var configViewCmd = &cobra.Command{ Short: "Display values currently set in the minikube config file", Long: "Display values currently set in the minikube config file.", Run: func(cmd *cobra.Command, args []string) { - err := configView() + err := View() if err != nil { exit.WithError("config view failed", err) } @@ -46,23 +47,24 @@ var configViewCmd = &cobra.Command{ } func init() { - configViewCmd.Flags().StringVar(&configViewFormat, "format", constants.DefaultConfigViewFormat, + configViewCmd.Flags().StringVar(&viewFormat, "format", constants.DefaultConfigViewFormat, `Go template format string for the config view 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#ConfigViewTemplate`) ConfigCmd.AddCommand(configViewCmd) } -func configView() error { +// View displays the current config +func View() error { cfg, err := config.ReadConfig() if err != nil { return err } for k, v := range cfg { - tmpl, err := template.New("view").Parse(configViewFormat) + tmpl, err := template.New("view").Parse(viewFormat) if err != nil { exit.WithError("Error creating view template", err) } - viewTmplt := ConfigViewTemplate{k, v} + viewTmplt := ViewTemplate{k, v} err = tmpl.Execute(os.Stdout, viewTmplt) if err != nil { exit.WithError("Error executing view template", err) diff --git a/cmd/minikube/cmd/env.go b/cmd/minikube/cmd/env.go index e808c6d76c64..f5cbf1478199 100644 --- a/cmd/minikube/cmd/env.go +++ b/cmd/minikube/cmd/env.go @@ -104,6 +104,7 @@ REM @FOR /f "tokens=*" %i IN ('minikube docker-env') DO @%i `, } +// ShellConfig represents the shell config type ShellConfig struct { Prefix string Delimiter string @@ -125,16 +126,20 @@ var ( defaultNoProxyGetter NoProxyGetter ) +// ShellDetector detects shell type ShellDetector interface { GetShell(string) (string, error) } +// LibmachineShellDetector detects shell, using libmachine type LibmachineShellDetector struct{} +// NoProxyGetter gets the no_proxy variable type NoProxyGetter interface { GetNoProxyVar() (string, string) } +// EnvNoProxyGetter gets the no_proxy variable, using environment type EnvNoProxyGetter struct{} func generateUsageHint(userShell string) string { @@ -274,6 +279,7 @@ func executeTemplateStdout(shellCfg *ShellConfig) error { return tmpl.Execute(os.Stdout, shellCfg) } +// GetShell detects the shell func (LibmachineShellDetector) GetShell(userShell string) (string, error) { if userShell != "" { return userShell, nil @@ -281,6 +287,7 @@ func (LibmachineShellDetector) GetShell(userShell string) (string, error) { return shell.Detect() } +// GetNoProxyVar gets the no_proxy var func (EnvNoProxyGetter) GetNoProxyVar() (string, string) { // first check for an existing lower case no_proxy var noProxyVar := "no_proxy" @@ -294,6 +301,7 @@ func (EnvNoProxyGetter) GetNoProxyVar() (string, string) { return noProxyVar, noProxyValue } +// GetDockerActive checks if Docker is active func GetDockerActive(host *host.Host) (bool, error) { statusCmd := `sudo systemctl is-active docker` status, err := host.RunSSHCommand(statusCmd) @@ -328,6 +336,9 @@ var dockerEnvCmd = &cobra.Command{ exit.WithCode(exit.Unavailable, `The docker host is currently not running`) } docker, err := GetDockerActive(host) + if err != nil { + exit.WithError("Error getting service status", err) + } if !docker { exit.WithCode(exit.Unavailable, `The docker service is currently not active`) } diff --git a/cmd/minikube/cmd/mount.go b/cmd/minikube/cmd/mount.go index ff56d0caceb9..4260178135af 100644 --- a/cmd/minikube/cmd/mount.go +++ b/cmd/minikube/cmd/mount.go @@ -19,8 +19,11 @@ package cmd import ( "net" "os" + "os/signal" + "strconv" "strings" "sync" + "syscall" "github.com/golang/glog" "github.com/spf13/cobra" @@ -34,16 +37,26 @@ import ( "k8s.io/minikube/third_party/go9p/ufs" ) +// nineP is the value of --type used for the 9p filesystem. +const nineP = "9p" + +// placeholders for flag values var mountIP string var mountVersion string +var mountType string var isKill bool var uid int var gid int -var msize int +var mSize int +var options []string +var mode uint + +// supportedFilesystems is a map of filesystem types to not warn against. +var supportedFilesystems = map[string]bool{nineP: true} // mountCmd represents the mount command var mountCmd = &cobra.Command{ - Use: "mount [flags] MOUNT_DIRECTORY(ex:\"/home\")", + Use: "mount [flags] :", Short: "Mounts the specified directory into minikube", Long: `Mounts the specified directory into minikube.`, Run: func(cmd *cobra.Command, args []string) { @@ -56,13 +69,12 @@ var mountCmd = &cobra.Command{ if len(args) != 1 { exit.Usage(`Please specify the directory to be mounted: - minikube mount HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY(ex:"/host-home:/vm-home")`) + minikube mount : (example: "/host-home:/vm-home")`) } mountString := args[0] idx := strings.LastIndex(mountString, ":") if idx == -1 { // no ":" was present - exit.Usage(`Mount directory must be in the form: - HOST_MOUNT_DIRECTORY:VM_MOUNT_DIRECTORY`) + exit.Usage(`mount argument %q must be in form: :`, mountString) } hostPath := mountString[:idx] vmPath := mountString[idx+1:] @@ -74,7 +86,7 @@ var mountCmd = &cobra.Command{ } } if len(vmPath) == 0 || !strings.HasPrefix(vmPath, "/") { - exit.Usage("The :VM_MOUNT_DIRECTORY must be an absolute path") + exit.Usage("Target directory %q must be an absolute path", vmPath) } var debugVal int if glog.V(1) { @@ -104,32 +116,88 @@ var mountCmd = &cobra.Command{ exit.WithCode(exit.Data, "error parsing the input ip address for mount") } } - 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 ...") port, err := cmdUtil.GetPort() if err != nil { exit.WithError("Error finding port for mount", err) } + + cfg := &cluster.MountConfig{ + Type: mountType, + UID: uid, + GID: gid, + Version: mountVersion, + MSize: mSize, + Port: port, + Mode: os.FileMode(mode), + Options: map[string]string{}, + } + + for _, o := range options { + if !strings.Contains(o, "=") { + cfg.Options[o] = "" + continue + } + parts := strings.Split(o, "=") + cfg.Options[parts[0]] = parts[1] + } + + console.OutStyle("mounting", "Mounting host path %s into VM as %s ...", hostPath, vmPath) + console.OutStyle("mount-options", "Mount options:") + console.OutStyle("option", "Type: %s", cfg.Type) + console.OutStyle("option", "UID: %d", cfg.UID) + console.OutStyle("option", "GID: %d", cfg.GID) + console.OutStyle("option", "Version: %s", cfg.Version) + console.OutStyle("option", "MSize: %d", cfg.MSize) + console.OutStyle("option", "Mode: %o (%s)", cfg.Mode, cfg.Mode) + console.OutStyle("option", "Options: %s", cfg.Options) + + // An escape valve to allow future hackers to try NFS, VirtFS, or other FS types. + if !supportedFilesystems[cfg.Type] { + console.OutLn("") + console.OutStyle("warning", "%s is not yet a supported filesystem. We will try anyways!", cfg.Type) + } + var wg sync.WaitGroup - wg.Add(1) + if cfg.Type == nineP { + wg.Add(1) + go func() { + console.OutStyle("fileserver", "Userspace file server: ") + ufs.StartServer(net.JoinHostPort(ip.String(), strconv.Itoa(port)), debugVal, hostPath) + wg.Done() + }() + } + + // Unmount if Ctrl-C or kill request is received. + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { - ufs.StartServer(net.JoinHostPort(ip.String(), port), debugVal, hostPath) - wg.Done() + for sig := range c { + console.OutStyle("unmount", "Unmounting %s ...", vmPath) + cluster.Unmount(host, vmPath) + exit.WithCode(exit.Interrupted, "Exiting due to %s signal", sig) + } }() - err = cluster.MountHost(api, ip, vmPath, port, mountVersion, uid, gid, msize) + + err = cluster.Mount(host, ip.String(), vmPath, cfg) if err != nil { - exit.WithError("failed to mount host", err) + exit.WithError("mount failed", err) } + console.OutStyle("success", "Successfully mounted %s to %s", hostPath, vmPath) + console.OutLn("") + console.OutStyle("notice", "NOTE: This process must stay alive for the mount to be accessible ...") wg.Wait() }, } func init() { mountCmd.Flags().StringVar(&mountIP, "ip", "", "Specify the ip that the mount should be setup on") + mountCmd.Flags().StringVar(&mountType, "type", nineP, "Specify the mount filesystem type (supported types: 9p)") mountCmd.Flags().StringVar(&mountVersion, "9p-version", constants.DefaultMountVersion, "Specify the 9p version that the mount should use") mountCmd.Flags().BoolVar(&isKill, "kill", false, "Kill the mount process spawned by minikube start") mountCmd.Flags().IntVar(&uid, "uid", 1001, "Default user id used for the mount") mountCmd.Flags().IntVar(&gid, "gid", 1001, "Default group id used for the mount") - mountCmd.Flags().IntVar(&msize, "msize", constants.DefaultMsize, "The number of bytes to use for 9p packet payload") + mountCmd.Flags().UintVar(&mode, "mode", 0755, "File permissions used for the mount") + mountCmd.Flags().StringSliceVar(&options, "options", []string{}, "Additional mount options, such as cache=fscache") + mountCmd.Flags().IntVar(&mSize, "msize", constants.DefaultMsize, "The number of bytes to use for 9p packet payload") RootCmd.AddCommand(mountCmd) } diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index fc1a81942cac..7379cc642578 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -49,7 +49,6 @@ import ( "k8s.io/minikube/pkg/minikube/logs" "k8s.io/minikube/pkg/minikube/machine" pkgutil "k8s.io/minikube/pkg/util" - "k8s.io/minikube/pkg/util/kubeconfig" "k8s.io/minikube/pkg/version" ) @@ -60,8 +59,8 @@ const ( humanReadableDiskSize = "disk-size" vmDriver = "vm-driver" xhyveDiskDriver = "xhyve-disk-driver" - NFSSharesRoot = "nfs-shares-root" - NFSShare = "nfs-share" + nfsSharesRoot = "nfs-shares-root" + nfsShare = "nfs-share" kubernetesVersion = "kubernetes-version" hostOnlyCIDR = "host-only-cidr" containerRuntime = "container-runtime" @@ -97,6 +96,9 @@ var ( apiServerNames []string apiServerIPs []net.IP extraOptions pkgutil.ExtraOptionSlice + + // proxyVars are variables we plumb through to the underlying container runtime + proxyVars = []string{"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY"} ) func init() { @@ -104,7 +106,7 @@ func init() { startCmd.Flags().Bool(createMount, false, "This will start the mount daemon and automatically mount files into minikube") startCmd.Flags().String(mountString, constants.DefaultMountDir+":"+constants.DefaultMountEndpoint, "The argument to pass the minikube mount command on start") startCmd.Flags().Bool(disableDriverMounts, false, "Disables the filesystem mounts provided by the hypervisors (vboxfs, xhyve-9p)") - startCmd.Flags().String(isoURL, constants.DefaultIsoUrl, "Location of the minikube iso") + startCmd.Flags().String(isoURL, constants.DefaultISOURL, "Location of the minikube iso") startCmd.Flags().String(vmDriver, constants.DefaultVMDriver, fmt.Sprintf("VM driver is one of: %v", constants.SupportedVMDrivers)) startCmd.Flags().Int(memory, constants.DefaultMemory, "Amount of RAM allocated to the minikube VM in MB") startCmd.Flags().Int(cpus, constants.DefaultCPUS, "Number of CPUs allocated to the minikube VM") @@ -113,8 +115,8 @@ func init() { startCmd.Flags().String(hypervVirtualSwitch, "", "The hyperv virtual switch name. Defaults to first found. (only supported with HyperV driver)") startCmd.Flags().String(kvmNetwork, "default", "The KVM network name. (only supported with KVM driver)") startCmd.Flags().String(xhyveDiskDriver, "ahci-hd", "The disk driver to use [ahci-hd|virtio-blk] (only supported with xhyve driver)") - startCmd.Flags().StringSlice(NFSShare, []string{}, "Local folders to share with Guest via NFS mounts (Only supported on with hyperkit now)") - startCmd.Flags().String(NFSSharesRoot, "/nfsshares", "Where to root the NFS Shares (defaults to /nfsshares, only supported with hyperkit now)") + startCmd.Flags().StringSlice(nfsShare, []string{}, "Local folders to share with Guest via NFS mounts (Only supported on with hyperkit now)") + startCmd.Flags().String(nfsSharesRoot, "/nfsshares", "Where to root the NFS Shares (defaults to /nfsshares, only supported with hyperkit now)") startCmd.Flags().StringArrayVar(&dockerEnv, "docker-env", nil, "Environment variables to pass to the Docker daemon. (format: key=value)") startCmd.Flags().StringArrayVar(&dockerOpt, "docker-opt", nil, "Specify arbitrary flags to pass to the Docker daemon. (format: key=value)") startCmd.Flags().Int(apiServerPort, pkgutil.APIServerPort, "The apiserver listening port") @@ -132,8 +134,7 @@ func init() { startCmd.Flags().String(networkPlugin, "", "The name of the network plugin") startCmd.Flags().Bool(enableDefaultCNI, false, "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \"--network-plugin=cni\"") startCmd.Flags().String(featureGates, "", "A set of key=value pairs that describe feature gates for alpha/experimental features.") - // TODO(tstromberg): Flip cacheImages to true once it can be stabilized - startCmd.Flags().Bool(cacheImages, false, "If true, cache docker images for the current bootstrapper and load them into the machine.") + startCmd.Flags().Bool(cacheImages, true, "If true, cache docker images for the current bootstrapper and load them into the machine.") startCmd.Flags().Var(&extraOptions, "extra-config", `A set of key=value pairs that describe configuration that may be passed to different components. The key should be '.' separated, and the first part before the dot is the component to apply the configuration to. @@ -165,14 +166,14 @@ func runStart(cmd *cobra.Command, args []string) { if err != nil && !os.IsNotExist(err) { exit.WithCode(exit.Data, "Unable to load config: %v", err) } - kVersion := validateKubernetesVersions(oldConfig) - config, err := generateConfig(cmd, kVersion) + k8sVersion := validateKubernetesVersions(oldConfig) + config, err := generateConfig(cmd, k8sVersion) if err != nil { exit.WithError("Failed to generate config", err) } var cacheGroup errgroup.Group - beginCacheImages(&cacheGroup, kVersion) + beginCacheImages(&cacheGroup, k8sVersion) // 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. @@ -240,18 +241,18 @@ func validateConfig() { } // beginCacheImages caches Docker images in the background -func beginCacheImages(g *errgroup.Group, kVersion string) { +func beginCacheImages(g *errgroup.Group, k8sVersion string) { if !viper.GetBool(cacheImages) { return } - console.OutStyle("caching", "Downloading Kubernetes %s images in the background ...", kVersion) + console.OutStyle("caching", "Downloading Kubernetes %s images in the background ...", k8sVersion) g.Go(func() error { - return machine.CacheImagesForBootstrapper(viper.GetString(imageRepository), kVersion, viper.GetString(cmdcfg.Bootstrapper)) + return machine.CacheImagesForBootstrapper(viper.GetString(imageRepository), k8sVersion, viper.GetString(cmdcfg.Bootstrapper)) }) } // generateConfig generates cfg.Config based on flags and supplied arguments -func generateConfig(cmd *cobra.Command, kVersion string) (cfg.Config, error) { +func generateConfig(cmd *cobra.Command, k8sVersion string) (cfg.Config, error) { r, err := cruntime.New(cruntime.Config{Type: viper.GetString(containerRuntime)}) if err != nil { return cfg.Config{}, err @@ -267,6 +268,17 @@ func generateConfig(cmd *cobra.Command, kVersion string) (cfg.Config, error) { } } + // Feed Docker our host proxy environment by default, so that it can pull images + if _, ok := r.(*cruntime.Docker); ok { + if !cmd.Flags().Changed("docker-env") { + for _, k := range proxyVars { + if v := os.Getenv(k); v != "" { + dockerEnv = append(dockerEnv, fmt.Sprintf("%s=%s", k, v)) + } + } + } + } + cfg := cfg.Config{ MachineConfig: cfg.MachineConfig{ MinikubeISO: viper.GetString(isoURL), @@ -278,8 +290,8 @@ func generateConfig(cmd *cobra.Command, kVersion string) (cfg.Config, error) { HyperkitVpnKitSock: viper.GetString(vpnkitSock), HyperkitVSockPorts: viper.GetStringSlice(vsockPorts), XhyveDiskDriver: viper.GetString(xhyveDiskDriver), - NFSShare: viper.GetStringSlice(NFSShare), - NFSSharesRoot: viper.GetString(NFSSharesRoot), + NFSShare: viper.GetStringSlice(nfsShare), + NFSSharesRoot: viper.GetString(nfsSharesRoot), DockerEnv: dockerEnv, DockerOpt: dockerOpt, InsecureRegistry: insecureRegistry, @@ -294,7 +306,7 @@ func generateConfig(cmd *cobra.Command, kVersion string) (cfg.Config, error) { NoVTXCheck: viper.GetBool(noVTXCheck), }, KubernetesConfig: cfg.KubernetesConfig{ - KubernetesVersion: kVersion, + KubernetesVersion: k8sVersion, NodePort: viper.GetInt(apiServerPort), NodeName: constants.DefaultNodeName, APIServerName: viper.GetString(apiServerName), @@ -374,7 +386,7 @@ func validateNetwork(h *host.Host) string { console.OutStyle("connectivity", "%q IP address is %s", cfg.GetMachineName(), ip) optSeen := false - for _, k := range []string{"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY"} { + for _, k := range proxyVars { if v := os.Getenv(k); v != "" { if !optSeen { console.OutStyle("internet", "Found network options:") @@ -440,15 +452,18 @@ func prepareHostEnvironment(api libmachine.API, kc cfg.KubernetesConfig) bootstr } // updateKubeConfig sets up kubectl -func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { +func updateKubeConfig(h *host.Host, c *cfg.Config) *pkgutil.KubeConfigSetup { addr, err := h.Driver.GetURL() if err != nil { exit.WithError("Failed to get driver URL", err) } addr = strings.Replace(addr, "tcp://", "https://", -1) addr = strings.Replace(addr, ":2376", ":"+strconv.Itoa(c.KubernetesConfig.NodePort), -1) + if c.KubernetesConfig.APIServerName != constants.APIServerName { + addr = strings.Replace(addr, c.KubernetesConfig.NodeIP, c.KubernetesConfig.APIServerName, -1) + } - kcs := &kubeconfig.KubeConfigSetup{ + kcs := &pkgutil.KubeConfigSetup{ ClusterName: cfg.GetMachineName(), ClusterServerAddress: addr, ClientCertificate: constants.MakeMiniPath("client.crt"), @@ -458,7 +473,7 @@ func updateKubeConfig(h *host.Host, c *cfg.Config) *kubeconfig.KubeConfigSetup { EmbedCerts: viper.GetBool(embedCerts), } kcs.SetKubeConfigFile(cmdutil.GetKubeConfigPath()) - if err := kubeconfig.SetupKubeConfig(kcs); err != nil { + if err := pkgutil.SetupKubeConfig(kcs); err != nil { exit.WithError("Failed to setup kubeconfig", err) } return kcs @@ -527,7 +542,7 @@ func bootstrapCluster(bs bootstrapper.Bootstrapper, r cruntime.Manager, runner b // validateCluster validates that the cluster is well-configured and healthy func validateCluster(bs bootstrapper.Bootstrapper, r cruntime.Manager, runner bootstrapper.CommandRunner, ip string) { console.OutStyle("verifying-noline", "Verifying component health ...") - kStat := func() (err error) { + k8sStat := func() (err error) { st, err := bs.GetKubeletStatus() console.Out(".") if err != nil || st != state.Running.String() { @@ -535,12 +550,12 @@ func validateCluster(bs bootstrapper.Bootstrapper, r cruntime.Manager, runner bo } return nil } - err := pkgutil.RetryAfter(20, kStat, 3*time.Second) + err := pkgutil.RetryAfter(20, k8sStat, 3*time.Second) if err != nil { exit.WithProblems("kubelet checks failed", err, logs.FindProblems(r, bs, runner)) } aStat := func() (err error) { - st, err := bs.GetApiServerStatus(net.ParseIP(ip)) + st, err := bs.GetAPIServerStatus(net.ParseIP(ip)) console.Out(".") if err != nil || st != state.Running.String() { return &pkgutil.RetriableError{Err: fmt.Errorf("apiserver status=%s err=%v", st, err)} diff --git a/cmd/minikube/cmd/status.go b/cmd/minikube/cmd/status.go index e6ea1af9d3ab..b39810318ade 100644 --- a/cmd/minikube/cmd/status.go +++ b/cmd/minikube/cmd/status.go @@ -31,15 +31,16 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" - "k8s.io/minikube/pkg/util/kubeconfig" + pkgutil "k8s.io/minikube/pkg/util" ) var statusFormat string +// Status represents the status type Status struct { Host string Kubelet string - ApiServer string + APIServer string Kubeconfig string } @@ -91,14 +92,14 @@ var statusCmd = &cobra.Command{ glog.Errorln("Error host driver ip status:", err) } - apiserverSt, err = clusterBootstrapper.GetApiServerStatus(ip) + apiserverSt, err = clusterBootstrapper.GetAPIServerStatus(ip) if err != nil { glog.Errorln("Error apiserver status:", err) } else if apiserverSt != state.Running.String() { returnCode |= clusterNotRunningStatusFlag } - ks, err := kubeconfig.GetKubeConfigStatus(ip, util.GetKubeConfigPath(), config.GetMachineName()) + ks, err := pkgutil.GetKubeConfigStatus(ip, util.GetKubeConfigPath(), config.GetMachineName()) if err != nil { glog.Errorln("Error kubeconfig status:", err) } @@ -116,7 +117,7 @@ var statusCmd = &cobra.Command{ status := Status{ Host: hostSt, Kubelet: kubeletSt, - ApiServer: apiserverSt, + APIServer: apiserverSt, Kubeconfig: kubeconfigSt, } tmpl, err := template.New("status").Parse(statusFormat) diff --git a/cmd/minikube/cmd/update-context.go b/cmd/minikube/cmd/update-context.go index b9e95d5a4d32..c2e9c0b78aa5 100644 --- a/cmd/minikube/cmd/update-context.go +++ b/cmd/minikube/cmd/update-context.go @@ -24,7 +24,7 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" - kcfg "k8s.io/minikube/pkg/util/kubeconfig" + "k8s.io/minikube/pkg/util" ) // updateContextCmd represents the update-context command @@ -44,7 +44,7 @@ var updateContextCmd = &cobra.Command{ if err != nil { exit.WithError("Error host driver ip status", err) } - updated, err := kcfg.UpdateKubeconfigIP(ip, constants.KubeconfigPath, machineName) + updated, err := util.UpdateKubeconfigIP(ip, constants.KubeconfigPath, machineName) if err != nil { exit.WithError("update config", err) } diff --git a/cmd/util/util.go b/cmd/util/util.go index 28105e727231..6cc8a12e043a 100644 --- a/cmd/util/util.go +++ b/cmd/util/util.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// package util is a hodge-podge of utility functions that should be moved elsewhere. +// Package util is a hodge-podge of utility functions that should be moved elsewhere. package util import ( @@ -28,8 +28,8 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) -// Ask the kernel for a free open port that is ready to use -func GetPort() (string, error) { +// GetPort asks the kernel for a free open port that is ready to use +func GetPort() (int, error) { addr, err := net.ResolveTCPAddr("tcp", "localhost:0") if err != nil { panic(err) @@ -37,12 +37,13 @@ func GetPort() (string, error) { l, err := net.ListenTCP("tcp", addr) if err != nil { - return "", errors.Errorf("Error accessing port %d", addr.Port) + return -1, errors.Errorf("Error accessing port %d", addr.Port) } defer l.Close() - return strconv.Itoa(l.Addr().(*net.TCPAddr).Port), nil + return l.Addr().(*net.TCPAddr).Port, nil } +// KillMountProcess kills the mount process, if it is running func KillMountProcess() error { out, err := ioutil.ReadFile(filepath.Join(constants.GetMinipath(), constants.MountProcessFileName)) if err != nil { @@ -59,6 +60,7 @@ func KillMountProcess() error { return mountProc.Kill() } +// GetKubeConfigPath gets the path to the first kubeconfig func GetKubeConfigPath() string { kubeConfigEnv := os.Getenv(constants.KubeconfigEnvVar) if kubeConfigEnv == "" { diff --git a/deploy/iso/minikube-iso/package/Config.in b/deploy/iso/minikube-iso/package/Config.in index c8958a279698..ba272fea468c 100644 --- a/deploy/iso/minikube-iso/package/Config.in +++ b/deploy/iso/minikube-iso/package/Config.in @@ -1,5 +1,6 @@ menu "System tools" source "$BR2_EXTERNAL_MINIKUBE_PATH/package/rkt-bin/Config.in" + source "$BR2_EXTERNAL_MINIKUBE_PATH/package/rktlet-master/Config.in" source "$BR2_EXTERNAL_MINIKUBE_PATH/package/runc-master/Config.in" source "$BR2_EXTERNAL_MINIKUBE_PATH/package/podman/Config.in" source "$BR2_EXTERNAL_MINIKUBE_PATH/package/crio-bin/Config.in" diff --git a/deploy/iso/minikube-iso/package/automount/minikube-automount b/deploy/iso/minikube-iso/package/automount/minikube-automount index 9e0fb740e3a2..1c0baec3e5de 100755 --- a/deploy/iso/minikube-iso/package/automount/minikube-automount +++ b/deploy/iso/minikube-iso/package/automount/minikube-automount @@ -26,25 +26,8 @@ if [ ! -n "$BOOT2DOCKER_DATA" ]; then dd if=$UNPARTITIONED_HD of=/userdata.tar bs=1 count=4096 2>/dev/null # Create the partition, format it and then mount it echo "NEW boot2docker managed disk image ($UNPARTITIONED_HD): formatting it for use" - - # Add a swap partition (so Docker doesn't complain about it missing) - (echo n; echo p; echo 2; echo ; echo +1000M ; echo w) | fdisk $UNPARTITIONED_HD - # Let kernel re-read partition table - partprobe - (echo t; echo 82; echo w) | fdisk $UNPARTITIONED_HD # Let kernel re-read partition table partprobe - # wait for the partition to actually exist, timeout after about 5 seconds - timer=0 - while [ "$timer" -lt 10 ]; do - if [ -b "${UNPARTITIONED_HD}2" ]; then - mkswap "${UNPARTITIONED_HD}2" && break - fi - echo "Waiting for ${UNPARTITIONED_HD}2 to exist." - timer=$((timer + 1)) - sleep 0.5 - done - # Add the data partition (echo n; echo p; echo 1; echo ; echo ; echo w) | fdisk $UNPARTITIONED_HD # Let kernel re-read partition table @@ -74,12 +57,6 @@ if [ ! -n "$BOOT2DOCKER_DATA" ]; then if [ $NON_NUL == 0 ]; then # Create the partition, format it and then mount it echo "NEW VMware boot2docker managed disk image ($UNPARTITIONED_HD): formatting it for use" - - # Add a swap partition (so Docker doesn't complain about it missing) - (echo n; echo p; echo 2; echo ; echo +1000M ; echo w) | fdisk $UNPARTITIONED_HD - (echo t; echo 82) | fdisk $UNPARTITIONED_HD - mkswap "${UNPARTITIONED_HD}2" - # Add the data partition (echo n; echo p; echo 1; echo ; echo ; echo w) | fdisk $UNPARTITIONED_HD BOOT2DOCKER_DATA=`echo "${UNPARTITIONED_HD}1"` mkfs.ext4 -i 2048 -L $LABEL $BOOT2DOCKER_DATA @@ -194,7 +171,6 @@ if [ -n "$BOOT2DOCKER_DATA" ]; then mkdir -p /var/run/minikube echo "PERSISTENT_DIR=\"/mnt/$PARTNAME\"" > /var/run/minikube/env fi -swapon "${UNPARTITIONED_HD}2" # /etc dirs are initialised from /usr/local, to allow the user/admin to customise mkdir -p /var/lib/boot2docker/etc/ diff --git a/deploy/iso/minikube-iso/package/crio-bin/crio-bin.hash b/deploy/iso/minikube-iso/package/crio-bin/crio-bin.hash index 2e0f76e2084e..67943232c223 100644 --- a/deploy/iso/minikube-iso/package/crio-bin/crio-bin.hash +++ b/deploy/iso/minikube-iso/package/crio-bin/crio-bin.hash @@ -2,3 +2,4 @@ sha256 d310d52706262009af886dbd3e8dcd09a339cdc3b57dc22a9121e6d6a87d2921 v1.8.4.t sha256 9f79cee99e272c9cfc561ae31235d84d4da59fd5c8b3d3ab6623bf9a92d90c5a v1.10.0.tar.gz sha256 09e53fd550f4f10108879131ee6b8ef1c367ce71a73dcf6350c4cc898751d8c1 v1.11.8.tar.gz sha256 92588998dbb79002c38f65f84602b5659f0d0ef1cd36b1a568a2e40269b66816 v1.13.0.tar.gz +sha256 48e7cf64a757d62a3edf214e1b93b74d99f090ca924f956ede2494a260eab2db v1.13.1.tar.gz diff --git a/deploy/iso/minikube-iso/package/crio-bin/crio-bin.mk b/deploy/iso/minikube-iso/package/crio-bin/crio-bin.mk index 0506b65b4ce5..3bd741cda731 100644 --- a/deploy/iso/minikube-iso/package/crio-bin/crio-bin.mk +++ b/deploy/iso/minikube-iso/package/crio-bin/crio-bin.mk @@ -4,7 +4,7 @@ # ################################################################################ -CRIO_BIN_VERSION = v1.13.0 +CRIO_BIN_VERSION = v1.13.1 CRIO_BIN_SITE = https://github.com/kubernetes-sigs/cri-o/archive CRIO_BIN_SOURCE = $(CRIO_BIN_VERSION).tar.gz CRIO_BIN_DEPENDENCIES = host-go libgpgme @@ -24,7 +24,6 @@ endef define CRIO_BIN_CONFIGURE_CMDS mkdir -p $(CRIO_BIN_GOPATH)/src/github.com/kubernetes-sigs ln -sf $(@D) $(CRIO_BIN_GOPATH)/src/github.com/kubernetes-sigs/cri-o - $(CRIO_BIN_ENV) $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) install.tools DESTDIR=$(TARGET_DIR) PREFIX=$(TARGET_DIR)/usr endef define CRIO_BIN_BUILD_CMDS diff --git a/deploy/iso/minikube-iso/package/podman/podman.mk b/deploy/iso/minikube-iso/package/podman/podman.mk index 86addddc0ba9..539d5192806f 100644 --- a/deploy/iso/minikube-iso/package/podman/podman.mk +++ b/deploy/iso/minikube-iso/package/podman/podman.mk @@ -20,7 +20,6 @@ define PODMAN_CONFIGURE_CMDS ln -sf $(@D) $(PODMAN_GOPATH)/src/github.com/containers/libpod mkdir -p $(PODMAN_GOPATH)/src/github.com/varlink ln -sf $(@D)/vendor/github.com/varlink/go $(PODMAN_GOPATH)/src/github.com/varlink/go - $(PODMAN_BIN_ENV) $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) install.tools DESTDIR=$(TARGET_DIR) PREFIX=$(TARGET_DIR)/usr endef define PODMAN_BUILD_CMDS diff --git a/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.hash b/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.hash index 871e8b2c8999..15f1b3c5fff6 100644 --- a/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.hash +++ b/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.hash @@ -4,4 +4,6 @@ sha256 2c00e816a5b470f29483d9660bd62e80da8f14e2a0ba79c841e15e1a28fbf975 rkt-v1. sha256 5aa2c2ac71f21bf3fc8a94b1bdd0b2c0f4060ad9054502b0a693f4632b093c2e rkt-v1.23.0.tar.gz.asc sha256 0ec396f1af7782e402d789e6e34e9257033efac5db71d740f9742f3469d02298 rkt-v1.24.0.tar.gz sha256 577a7a7e3512c0116b3642c710304d4f36a1f66c7e34ec8753dae168a29761e3 rkt-v1.24.0.tar.gz.asc -sha256 16b93904e4b3133fe4b5f95f46e3db998c3b2f9d9cee6d4c2eb531f98028bcb3 app-signing-pubkey.gpg +sha256 f6a51fe1d11aaecef965cca729f260f9ea691f6576e8698b49a2daedfc48c427 rkt-v1.30.0.tar.gz +sha256 874d8bcf9dd09599b2d090259485a49a6c1f4a74f55065dec8ac37e283c27592 rkt-v1.30.0.tar.gz.asc +sha256 b7a769456e62d10a042a4fad79f1fe595d8c392490a6ff611c759c0669d99a97 app-signing-pubkey.gpg diff --git a/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.mk b/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.mk index 255b3298d033..99d064ceb16d 100644 --- a/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.mk +++ b/deploy/iso/minikube-iso/package/rkt-bin/rkt-bin.mk @@ -4,7 +4,7 @@ # ################################################################################ -RKT_BIN_VERSION = 1.24.0 +RKT_BIN_VERSION = 1.30.0 RKT_BIN_SITE = https://github.com/coreos/rkt/releases/download/v$(RKT_BIN_VERSION) RKT_BIN_SOURCE = rkt-v$(RKT_BIN_VERSION).tar.gz diff --git a/deploy/iso/minikube-iso/package/rktlet-master/Config.in b/deploy/iso/minikube-iso/package/rktlet-master/Config.in new file mode 100644 index 000000000000..b95d15e3939f --- /dev/null +++ b/deploy/iso/minikube-iso/package/rktlet-master/Config.in @@ -0,0 +1,16 @@ +config BR2_PACKAGE_RKTLET_MASTER + bool "rktlet-master" + default y + depends on BR2_PACKAGE_HOST_GO_ARCH_SUPPORTS + depends on BR2_PACKAGE_HOST_GO_CGO_LINKING_SUPPORTS + depends on BR2_TOOLCHAIN_HAS_THREADS + help + The rkt implementation of the Kubernetes + Container Runtime Interface. + + https://github.com/kubernetes-incubator/rktlet + +comment "rktlet needs a toolchain w/ threads" + depends on BR2_PACKAGE_HOST_GO_ARCH_SUPPORTS && \ + BR2_PACKAGE_HOST_GO_CGO_LINKING_SUPPORTS + depends on !BR2_TOOLCHAIN_HAS_THREADS diff --git a/deploy/iso/minikube-iso/package/rktlet-master/fd7fc6bf4a25f03c22e5f6e30f3d9f12c468afcb.tar.gz b/deploy/iso/minikube-iso/package/rktlet-master/fd7fc6bf4a25f03c22e5f6e30f3d9f12c468afcb.tar.gz new file mode 100644 index 000000000000..8cc4a9d5b76d Binary files /dev/null and b/deploy/iso/minikube-iso/package/rktlet-master/fd7fc6bf4a25f03c22e5f6e30f3d9f12c468afcb.tar.gz differ diff --git a/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.hash b/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.hash new file mode 100644 index 000000000000..5d60a49a0a3d --- /dev/null +++ b/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.hash @@ -0,0 +1,2 @@ +# Locally computed +sha256 12254af0f8d9b1f653f20e943dbbda42b74f6eafe7331db74a32857e44efdc6f fd7fc6bf4a25f03c22e5f6e30f3d9f12c468afcb.tar.gz diff --git a/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.mk b/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.mk new file mode 100644 index 000000000000..032999c872c5 --- /dev/null +++ b/deploy/iso/minikube-iso/package/rktlet-master/rktlet-master.mk @@ -0,0 +1,59 @@ +################################################################################ +# +# rktlet +# +################################################################################ + +# HEAD as of 2018-05-28 +RKTLET_MASTER_COMMIT = fd7fc6bf4a25f03c22e5f6e30f3d9f12c468afcb +RKTLET_MASTER_VERSION = v0.1.0-21-gfd7fc6b +RKTLET_MASTER_SITE = https://github.com/kubernetes-incubator/rktlet/archive +RKTLET_MASTER_SOURCE = $(RKTLET_MASTER_COMMIT).tar.gz +RKTLET_MASTER_LICENSE = Apache-2.0 +RKTLET_MASTER_LICENSE_FILES = LICENSE + +RKTLET_MASTER_DEPENDENCIES = host-go + +RKTLET_MASTER_GOPATH = "$(@D)/Godeps/_workspace" +RKTLET_MASTER_MAKE_ENV = $(HOST_GO_TARGET_ENV) \ + CGO_ENABLED=1 \ + GOBIN="$(@D)/bin" \ + GOPATH="$(RKTLET_MASTER_GOPATH)" \ + PATH=$(BR_PATH) + +RKTLET_MASTER_GLDFLAGS = \ + -buildmode=pie -X github.com/kubernetes-incubator/rktlet/version.Version=$(RKTLET_MASTER_VERSION) + +ifeq ($(BR2_STATIC_LIBS),y) +RKTLET_MASTER_GLDFLAGS += -extldflags '-static' +endif + +RKTLET_MASTER_GOTAGS = cgo static_build + +ifeq ($(BR2_PACKAGE_LIBSECCOMP),y) +RKTLET_MASTER_GOTAGS += seccomp +RKTLET_MASTER_DEPENDENCIES += libseccomp host-pkgconf +endif + +define RKTLET_MASTER_CONFIGURE_CMDS + mkdir -p $(RKTLET_MASTER_GOPATH)/src/github.com/kubernetes-incubator + ln -s $(@D) $(RKTLET_MASTER_GOPATH)/src/github.com/kubernetes-incubator/rktlet +endef + +define RKTLET_MASTER_BUILD_CMDS + cd $(@D) && $(RKTLET_MASTER_MAKE_ENV) $(HOST_DIR)/usr/bin/go \ + build -v -o $(@D)/bin/rktlet \ + -tags "$(RKTLET_MASTER_GOTAGS)" -ldflags "$(RKTLET_MASTER_GLDFLAGS)" github.com/kubernetes-incubator/rktlet/cmd/server +endef + +define RKTLET_MASTER_INSTALL_TARGET_CMDS + $(INSTALL) -D -m 0755 $(@D)/bin/rktlet $(TARGET_DIR)/usr/bin/rktlet +endef + +define RKTLET_MASTER_INSTALL_INIT_SYSTEMD + $(INSTALL) -Dm644 \ + $(BR2_EXTERNAL_MINIKUBE_PATH)/package/rktlet-master/rktlet.service \ + $(TARGET_DIR)/usr/lib/systemd/system/rktlet.service +endef + +$(eval $(generic-package)) diff --git a/deploy/iso/minikube-iso/package/rktlet-master/rktlet.service b/deploy/iso/minikube-iso/package/rktlet-master/rktlet.service new file mode 100644 index 000000000000..d7720c3039c9 --- /dev/null +++ b/deploy/iso/minikube-iso/package/rktlet-master/rktlet.service @@ -0,0 +1,12 @@ +[Unit] +Description=rktlet: The rkt implementation of a Kubernetes Container Runtime +Documentation=https://github.com/kubernetes-incubator/rktlet/tree/master/docs + +[Service] +ExecStart=/usr/bin/rktlet +Restart=always +StartLimitInterval=0 +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/minikube/release_sanity_test.go b/deploy/minikube/release_sanity_test.go index 7aedbabaf770..38cc2f907f60 100644 --- a/deploy/minikube/release_sanity_test.go +++ b/deploy/minikube/release_sanity_test.go @@ -31,7 +31,7 @@ import ( "k8s.io/minikube/pkg/util" ) -func getShaFromURL(url string) (string, error) { +func getSHAFromURL(url string) (string, error) { fmt.Println("Downloading: ", url) r, err := http.Get(url) if err != nil { @@ -57,7 +57,7 @@ func TestReleasesJson(t *testing.T) { fmt.Printf("Checking release: %s\n", r.Name) for platform, sha := range r.Checksums { fmt.Printf("Checking SHA for %s.\n", platform) - actualSha, err := getShaFromURL(util.GetBinaryDownloadURL(r.Name, platform)) + actualSha, err := getSHAFromURL(util.GetBinaryDownloadURL(r.Name, platform)) if err != nil { t.Errorf("Error calculating SHA for %s-%s. Error: %v", r.Name, platform, err) continue diff --git a/pkg/drivers/drivers.go b/pkg/drivers/drivers.go index 639d30b436cb..f378967601d3 100644 --- a/pkg/drivers/drivers.go +++ b/pkg/drivers/drivers.go @@ -30,18 +30,20 @@ import ( "github.com/pkg/errors" ) +// GetDiskPath returns the path of the machine disk image func GetDiskPath(d *drivers.BaseDriver) string { return filepath.Join(d.ResolveStorePath("."), d.GetMachineName()+".rawdisk") } +// CommonDriver is the common driver base class type CommonDriver struct{} -//Not implemented yet +// GetCreateFlags is not implemented yet func (d *CommonDriver) GetCreateFlags() []mcnflag.Flag { return nil } -//Not implemented yet +// SetConfigFromFlags is not implemented yet func (d *CommonDriver) SetConfigFromFlags(flags drivers.DriverOptions) error { return nil } @@ -87,6 +89,7 @@ func Restart(d drivers.Driver) error { return nil } +// MakeDiskImage makes a boot2docker VM disk image. func MakeDiskImage(d *drivers.BaseDriver, boot2dockerURL string, diskSize int) error { //TODO(r2d4): rewrite this, not using b2dutils b2dutils := mcnutils.NewB2dUtils(d.StorePath) diff --git a/pkg/drivers/hyperkit/iso.go b/pkg/drivers/hyperkit/iso.go index 14503e1b2f6d..85c859304c85 100644 --- a/pkg/drivers/hyperkit/iso.go +++ b/pkg/drivers/hyperkit/iso.go @@ -26,6 +26,7 @@ import ( "github.com/hooklift/iso9660" ) +// ExtractFile extracts a file from an ISO func ExtractFile(isoPath, srcPath, destPath string) error { iso, err := os.Open(isoPath) defer iso.Close() @@ -53,7 +54,7 @@ func ExtractFile(isoPath, srcPath, destPath string) error { return err } -func ReadFile(isoPath, srcPath string) (string, error) { +func readFile(isoPath, srcPath string) (string, error) { iso, err := os.Open(isoPath) defer iso.Close() if err != nil { diff --git a/pkg/drivers/hyperkit/network.go b/pkg/drivers/hyperkit/network.go index a699e071ab62..27cc41f5724b 100644 --- a/pkg/drivers/hyperkit/network.go +++ b/pkg/drivers/hyperkit/network.go @@ -30,11 +30,15 @@ import ( ) const ( - LeasesPath = "/var/db/dhcpd_leases" - VMNetDomain = "/Library/Preferences/SystemConfiguration/com.apple.vmnet" + // LeasesPath is the path to dhcpd leases + LeasesPath = "/var/db/dhcpd_leases" + // VMNetDomain is the domain for vmnet + VMNetDomain = "/Library/Preferences/SystemConfiguration/com.apple.vmnet" + // SharedNetAddrKey is the key for the network address SharedNetAddrKey = "Shared_Net_Address" ) +// DHCPEntry holds a parsed DNS entry type DHCPEntry struct { Name string IPAddress string @@ -43,6 +47,7 @@ type DHCPEntry struct { Lease string } +// GetIPAddressByMACAddress gets the IP address of a MAC address func GetIPAddressByMACAddress(mac string) (string, error) { return getIPAddressFromFile(mac, LeasesPath) } @@ -119,6 +124,7 @@ func trimMacAddress(rawUUID string) string { return mac } +// GetNetAddr gets the network address for vmnet func GetNetAddr() (net.IP, error) { plistPath := VMNetDomain + ".plist" if _, err := os.Stat(plistPath); err != nil { diff --git a/pkg/drivers/kvm/gpu.go b/pkg/drivers/kvm/gpu.go index bdd84e4dd313..0a7dbeda6765 100644 --- a/pkg/drivers/kvm/gpu.go +++ b/pkg/drivers/kvm/gpu.go @@ -31,7 +31,7 @@ import ( var sysFsPCIDevicesPath = "/sys/bus/pci/devices/" var sysKernelIOMMUGroupsPath = "/sys/kernel/iommu_groups/" -const nvidiaVendorId = "0x10de" +const nvidiaVendorID = "0x10de" const devicesTmpl = ` @@ -50,6 +50,7 @@ const devicesTmpl = ` {{end}} ` +// PCIDevice holds a parsed PCI device type PCIDevice struct { Domain string Bus string @@ -127,8 +128,8 @@ func getPassthroughableNVIDIADevices() ([]string, error) { } // Check if this is an NVIDIA device - if strings.EqualFold(strings.TrimSpace(string(content)), nvidiaVendorId) { - log.Infof("Found device %v with NVIDIA's vendorId %v", device.Name(), nvidiaVendorId) + if strings.EqualFold(strings.TrimSpace(string(content)), nvidiaVendorID) { + log.Infof("Found device %v with NVIDIA's vendorId %v", device.Name(), nvidiaVendorID) found = true // Check whether it's unbound. We don't want the device to be bound to nvidia/nouveau etc. @@ -195,14 +196,12 @@ func isUnbound(device string) bool { if os.IsNotExist(err) { log.Infof("%v is not bound to any driver", device) return true - } else { - module := filepath.Base(modulePath) - if module == "pci_stub" || module == "vfio_pci" { - log.Infof("%v is bound to a stub module: %v", device, module) - return true - } else { - log.Infof("%v is bound to a non-stub module: %v", device, module) - return false - } } + module := filepath.Base(modulePath) + if module == "pci_stub" || module == "vfio_pci" { + log.Infof("%v is bound to a stub module: %v", device, module) + return true + } + log.Infof("%v is bound to a non-stub module: %v", device, module) + return false } diff --git a/pkg/drivers/kvm/kvm.go b/pkg/drivers/kvm/kvm.go index 735e6d169bc1..793abbe49210 100644 --- a/pkg/drivers/kvm/kvm.go +++ b/pkg/drivers/kvm/kvm.go @@ -34,6 +34,7 @@ import ( pkgdrivers "k8s.io/minikube/pkg/drivers" ) +// Driver is the machine driver for KVM type Driver struct { *drivers.BaseDriver *pkgdrivers.CommonDriver @@ -83,6 +84,7 @@ const ( defaultNetworkName = "default" ) +// NewDriver creates a new driver for a host func NewDriver(hostName, storePath string) *Driver { return &Driver{ BaseDriver: &drivers.BaseDriver{ @@ -91,7 +93,7 @@ func NewDriver(hostName, storePath string) *Driver { SSHUser: "docker", }, CommonDriver: &pkgdrivers.CommonDriver{}, - Boot2DockerURL: constants.DefaultIsoUrl, + Boot2DockerURL: constants.DefaultISOURL, CPU: constants.DefaultCPUS, DiskSize: util.CalculateDiskSizeInMB(constants.DefaultDiskSize), Memory: constants.DefaultMemory, @@ -102,6 +104,7 @@ func NewDriver(hostName, storePath string) *Driver { } } +// PreCommandCheck checks the connection before issuing a command func (d *Driver) PreCommandCheck() error { conn, err := getConnection() if err != nil { @@ -116,6 +119,7 @@ func (d *Driver) PreCommandCheck() error { return nil } +// GetURL returns a Docker compatible host URL for connecting to this host func (d *Driver) GetURL() (string, error) { if err := d.PreCommandCheck(); err != nil { return "", errors.Wrap(err, "getting URL, precheck failed") @@ -132,6 +136,7 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s:2376", ip), nil } +// GetState returns the state that the host is in (running, stopped, etc) func (d *Driver) GetState() (state.State, error) { dom, conn, err := d.getDomain() if err != nil { @@ -176,6 +181,7 @@ func (d *Driver) GetState() (state.State, error) { } } +// GetIP returns an IP or hostname that this host is available at func (d *Driver) GetIP() (string, error) { s, err := d.GetState() if err != nil { @@ -192,14 +198,17 @@ func (d *Driver) GetIP() (string, error) { return ip, nil } +// GetSSHHostname returns hostname for use with ssh func (d *Driver) GetSSHHostname() (string, error) { return d.GetIP() } +// DriverName returns the name of the driver func (d *Driver) DriverName() string { return "kvm2" } +// Kill stops a host forcefully, including any containers that we are managing. func (d *Driver) Kill() error { dom, conn, err := d.getDomain() if err != nil { @@ -210,10 +219,12 @@ func (d *Driver) Kill() error { return dom.Destroy() } +// Restart a host func (d *Driver) Restart() error { return pkgdrivers.Restart(d) } +// Start a host func (d *Driver) Start() error { // if somebody/something deleted the network in the meantime, // we might need to recreate it. It's (nearly) a noop if the network exists. @@ -274,6 +285,7 @@ func (d *Driver) Start() error { return nil } +// Create a host using the driver's config func (d *Driver) Create() error { log.Info("Creating machine...") log.Info("Creating network...") @@ -323,6 +335,7 @@ func (d *Driver) Create() error { return d.Start() } +// Stop a host gracefully func (d *Driver) Stop() error { d.IPAddress = "" s, err := d.GetState() @@ -359,6 +372,7 @@ func (d *Driver) Stop() error { return fmt.Errorf("Could not stop VM, current state %s", s.String()) } +// Remove a host func (d *Driver) Remove() error { log.Debug("Removing machine...") conn, err := getConnection() diff --git a/pkg/drivers/none/none.go b/pkg/drivers/none/none.go index 716a2eb1264b..76ca08f08223 100644 --- a/pkg/drivers/none/none.go +++ b/pkg/drivers/none/none.go @@ -39,7 +39,7 @@ var cleanupPaths = []string{ "/var/lib/minikube", } -// none Driver is a driver designed to run kubeadm w/o VM management, and assumes systemctl. +// Driver is a driver designed to run kubeadm w/o VM management, and assumes systemctl. // https://github.com/kubernetes/minikube/blob/master/docs/vmdriver-none.md type Driver struct { *drivers.BaseDriver @@ -79,6 +79,7 @@ func (d *Driver) PreCreateCheck() error { return d.runtime.Available() } +// Create a host using the driver's config func (d *Driver) Create() error { // creation for the none driver is handled by commands.go return nil diff --git a/pkg/gvisor/enable.go b/pkg/gvisor/enable.go index 2268c7381d2e..89a66e0642bd 100644 --- a/pkg/gvisor/enable.go +++ b/pkg/gvisor/enable.go @@ -117,7 +117,7 @@ func runsc() error { return downloadFileToDest(constants.GvisorURL, dest) } -// downloadFileToDest downlaods the given file to the dest +// downloadFileToDest downloads the given file to the dest // if something already exists at dest, first remove it func downloadFileToDest(url, dest string) error { client := &http.Client{} diff --git a/pkg/minikube/assets/addons.go b/pkg/minikube/assets/addons.go index 70420683398d..d882492ddfc0 100644 --- a/pkg/minikube/assets/addons.go +++ b/pkg/minikube/assets/addons.go @@ -29,12 +29,14 @@ import ( "k8s.io/minikube/pkg/util" ) +// Addon is a named list of assets, that can be enabled type Addon struct { Assets []*BinDataAsset enabled bool addonName string } +// NewAddon creates a new Addon func NewAddon(assets []*BinDataAsset, enabled bool, addonName string) *Addon { a := &Addon{ Assets: assets, @@ -44,6 +46,7 @@ func NewAddon(assets []*BinDataAsset, enabled bool, addonName string) *Addon { return a } +// IsEnabled checks if an Addon is enabled func (a *Addon) IsEnabled() (bool, error) { addonStatusText, err := config.Get(a.addonName) if err == nil { @@ -56,6 +59,7 @@ func (a *Addon) IsEnabled() (bool, error) { return a.enabled, nil } +// Addons is the list of addons var Addons = map[string]*Addon{ "addon-manager": NewAddon([]*BinDataAsset{ NewBinDataAsset( @@ -319,6 +323,8 @@ var Addons = map[string]*Addon{ }, false, "gvisor"), } +// AddMinikubeDirAssets adds all addons and files to the list +// of files to be copied to the vm. func AddMinikubeDirAssets(assets *[]CopyableFile) error { if err := addMinikubeDirToAssets(constants.MakeMiniPath("addons"), constants.AddonsPath, assets); err != nil { return errors.Wrap(err, "adding addons folder to assets") diff --git a/pkg/minikube/assets/vm_assets.go b/pkg/minikube/assets/vm_assets.go index 8c5d5a463b9e..283a8aa36a15 100644 --- a/pkg/minikube/assets/vm_assets.go +++ b/pkg/minikube/assets/vm_assets.go @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" ) +// CopyableFile is something that can be copied type CopyableFile interface { io.Reader GetLength() int @@ -35,6 +36,7 @@ type CopyableFile interface { GetPermissions() string } +// BaseAsset is the base asset class type BaseAsset struct { data []byte reader io.Reader @@ -45,30 +47,37 @@ type BaseAsset struct { Permissions string } +// GetAssetName returns asset name func (b *BaseAsset) GetAssetName() string { return b.AssetName } +// GetTargetDir returns target dir func (b *BaseAsset) GetTargetDir() string { return b.TargetDir } +// GetTargetName returns target name func (b *BaseAsset) GetTargetName() string { return b.TargetName } +// GetPermissions returns permissions func (b *BaseAsset) GetPermissions() string { return b.Permissions } +// FileAsset is an asset using a file type FileAsset struct { BaseAsset } +// NewMemoryAssetTarget creates a new MemoryAsset, with target func NewMemoryAssetTarget(d []byte, targetPath, permissions string) *MemoryAsset { return NewMemoryAsset(d, path.Dir(targetPath), path.Base(targetPath), permissions) } +// NewFileAsset creates a new FileAsset func NewFileAsset(assetName, targetDir, targetName, permissions string) (*FileAsset, error) { f := &FileAsset{ BaseAsset{ @@ -86,6 +95,7 @@ func NewFileAsset(assetName, targetDir, targetName, permissions string) (*FileAs return f, nil } +// GetLength returns the file length, or 0 (on error) func (f *FileAsset) GetLength() int { file, err := os.Open(f.AssetName) defer file.Close() @@ -106,18 +116,22 @@ func (f *FileAsset) Read(p []byte) (int, error) { return f.reader.Read(p) } +// MemoryAsset is a memory-based asset type MemoryAsset struct { BaseAsset } +// GetLength returns length func (m *MemoryAsset) GetLength() int { return m.Length } +// Read reads the asset func (m *MemoryAsset) Read(p []byte) (int, error) { return m.reader.Read(p) } +// NewMemoryAsset creates a new MemoryAsset func NewMemoryAsset(d []byte, targetDir, targetName, permissions string) *MemoryAsset { m := &MemoryAsset{ BaseAsset{ @@ -133,11 +147,13 @@ func NewMemoryAsset(d []byte, targetDir, targetName, permissions string) *Memory return m } +// BinDataAsset is a bindata (binary data) asset type BinDataAsset struct { BaseAsset template *template.Template } +// NewBinDataAsset creates a new BinDataAsset func NewBinDataAsset(assetName, targetDir, targetName, permissions string, isTemplate bool) *BinDataAsset { m := &BinDataAsset{ BaseAsset: BaseAsset{ @@ -202,10 +218,12 @@ func (m *BinDataAsset) Evaluate(data interface{}) (*MemoryAsset, error){ return NewMemoryAsset(buf.Bytes(), m.GetTargetDir(), m.GetTargetName(), m.GetPermissions()), nil } +// GetLength returns length func (m *BinDataAsset) GetLength() int { return m.Length } +// Read reads the asset func (m *BinDataAsset) Read(p []byte) (int, error) { return m.reader.Read(p) } diff --git a/pkg/minikube/bootstrapper/bootstrapper.go b/pkg/minikube/bootstrapper/bootstrapper.go index ecc7197f2bc3..e7d9ed4bbb85 100644 --- a/pkg/minikube/bootstrapper/bootstrapper.go +++ b/pkg/minikube/bootstrapper/bootstrapper.go @@ -43,17 +43,19 @@ type Bootstrapper interface { LogCommands(LogOptions) map[string]string SetupCerts(cfg config.KubernetesConfig) error GetKubeletStatus() (string, error) - GetApiServerStatus(net.IP) (string, error) + GetAPIServerStatus(net.IP) (string, error) } const ( + // BootstrapperTypeKubeadm is the kubeadm bootstrapper type BootstrapperTypeKubeadm = "kubeadm" ) +// GetCachedImageList returns the list of images for a version func GetCachedImageList(imageRepository string, version string, bootstrapper string) []string { switch bootstrapper { case BootstrapperTypeKubeadm: - _, images := constants.GetKubeadmImages(imageRepository, version) + _, images := constants.GetKubeadmCachedImages(imageRepository, version) return images default: return []string{} diff --git a/pkg/minikube/bootstrapper/certs.go b/pkg/minikube/bootstrapper/certs.go index 984973d1caae..bde242f453a1 100644 --- a/pkg/minikube/bootstrapper/certs.go +++ b/pkg/minikube/bootstrapper/certs.go @@ -31,7 +31,6 @@ import ( "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/util" - "k8s.io/minikube/pkg/util/kubeconfig" ) var ( @@ -65,7 +64,7 @@ func SetupCerts(cmd CommandRunner, k8s config.KubernetesConfig) error { copyableFiles = append(copyableFiles, certFile) } - kubeCfgSetup := &kubeconfig.KubeConfigSetup{ + kubeCfgSetup := &util.KubeConfigSetup{ ClusterName: k8s.NodeName, ClusterServerAddress: "https://localhost:8443", ClientCertificate: path.Join(util.DefaultCertPath, "apiserver.crt"), @@ -75,7 +74,7 @@ func SetupCerts(cmd CommandRunner, k8s config.KubernetesConfig) error { } kubeCfg := api.NewConfig() - err := kubeconfig.PopulateKubeConfig(kubeCfgSetup, kubeCfg) + err := util.PopulateKubeConfig(kubeCfgSetup, kubeCfg) if err != nil { return errors.Wrap(err, "populating kubeconfig") } diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index df3aa1d3c7ae..e4ec43e60549 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -57,8 +57,7 @@ var SkipPreflights = []string{ "FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml", "FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml", "FileAvailable--etc-kubernetes-manifests-etcd.yaml", - // We use --ignore-preflight-errors=Swap since minikube.iso allocates a swap partition. - // (it should probably stop doing this, though...) + // So that "none" driver users don't have to reconfigure their machine "Swap", // We use --ignore-preflight-errors=CRI since /var/run/dockershim.sock is not present. // (because we start kubelet with an invalid config) @@ -86,11 +85,13 @@ var PodsByLayer = []pod{ // SkipAdditionalPreflights are additional preflights we skip depending on the runtime in use. var SkipAdditionalPreflights = map[string][]string{} -type KubeadmBootstrapper struct { +// Bootstrapper is a bootstrapper using kubeadm +type Bootstrapper struct { c bootstrapper.CommandRunner } -func NewKubeadmBootstrapper(api libmachine.API) (*KubeadmBootstrapper, error) { +// NewKubeadmBootstrapper creates a new kubeadm.Bootstrapper +func NewKubeadmBootstrapper(api libmachine.API) (*Bootstrapper, error) { h, err := api.Load(config.GetMachineName()) if err != nil { return nil, errors.Wrap(err, "getting api client") @@ -99,10 +100,11 @@ func NewKubeadmBootstrapper(api libmachine.API) (*KubeadmBootstrapper, error) { if err != nil { return nil, errors.Wrap(err, "command runner") } - return &KubeadmBootstrapper{c: runner}, nil + return &Bootstrapper{c: runner}, nil } -func (k *KubeadmBootstrapper) GetKubeletStatus() (string, error) { +// GetKubeletStatus returns the kubelet status +func (k *Bootstrapper) GetKubeletStatus() (string, error) { statusCmd := `sudo systemctl is-active kubelet` status, err := k.c.CombinedOutput(statusCmd) if err != nil { @@ -120,7 +122,8 @@ func (k *KubeadmBootstrapper) GetKubeletStatus() (string, error) { return state.Error.String(), nil } -func (k *KubeadmBootstrapper) GetApiServerStatus(ip net.IP) (string, error) { +// GetAPIServerStatus returns the api-server status +func (k *Bootstrapper) GetAPIServerStatus(ip net.IP) (string, error) { url := fmt.Sprintf("https://%s:%d/healthz", ip, util.APIServerPort) // To avoid: x509: certificate signed by unknown authority tr := &http.Transport{ @@ -140,7 +143,7 @@ func (k *KubeadmBootstrapper) GetApiServerStatus(ip net.IP) (string, error) { } // LogCommands returns a map of log type to a command which will display that log. -func (k *KubeadmBootstrapper) LogCommands(o bootstrapper.LogOptions) map[string]string { +func (k *Bootstrapper) LogCommands(o bootstrapper.LogOptions) map[string]string { var kubelet strings.Builder kubelet.WriteString("journalctl -u kubelet") if o.Lines > 0 { @@ -164,7 +167,8 @@ func (k *KubeadmBootstrapper) LogCommands(o bootstrapper.LogOptions) map[string] } } -func (k *KubeadmBootstrapper) StartCluster(k8s config.KubernetesConfig) error { +// StartCluster starts the cluster +func (k *Bootstrapper) StartCluster(k8s config.KubernetesConfig) error { version, err := ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") @@ -206,7 +210,7 @@ func (k *KubeadmBootstrapper) StartCluster(k8s config.KubernetesConfig) error { } } - if err := waitForPods(false); err != nil { + if err := waitForPods(k8s, false); err != nil { return errors.Wrap(err, "wait") } @@ -216,7 +220,7 @@ func (k *KubeadmBootstrapper) StartCluster(k8s config.KubernetesConfig) error { } // Make sure elevating privileges didn't screw anything up - if err := waitForPods(true); err != nil { + if err := waitForPods(k8s, true); err != nil { return errors.Wrap(err, "wait") } @@ -253,7 +257,12 @@ func addAddons(files *[]assets.CopyableFile, data interface{}) error { } // waitForPods waits until the important Kubernetes pods are in running state -func waitForPods(quiet bool) error { +func waitForPods(k8s config.KubernetesConfig, quiet bool) error { + // Do not wait for "k8s-app" pods in the case of CNI, as they are managed + // by a CNI plugin which is usually started after minikube has been brought + // up. Otherwise, minikube won't start, as "k8s-app" pods are not ready. + componentsOnly := k8s.NetworkPlugin == "cni" + if !quiet { console.OutStyle("waiting-pods", "Waiting for pods:") } @@ -263,6 +272,10 @@ func waitForPods(quiet bool) error { } for _, p := range PodsByLayer { + if componentsOnly && p.key != "component" { + continue + } + if !quiet { console.Out(" %s", p.name) } @@ -278,7 +291,7 @@ func waitForPods(quiet bool) error { } // RestartCluster restarts the Kubernetes cluster configured by kubeadm -func (k *KubeadmBootstrapper) RestartCluster(k8s config.KubernetesConfig) error { +func (k *Bootstrapper) RestartCluster(k8s config.KubernetesConfig) error { version, err := ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") @@ -305,7 +318,7 @@ func (k *KubeadmBootstrapper) RestartCluster(k8s config.KubernetesConfig) error } } - if err := waitForPods(false); err != nil { + if err := waitForPods(k8s, false); err != nil { return errors.Wrap(err, "wait") } @@ -315,7 +328,7 @@ func (k *KubeadmBootstrapper) RestartCluster(k8s config.KubernetesConfig) error } // Make sure the kube-proxy restart didn't screw anything up. - if err := waitForPods(true); err != nil { + if err := waitForPods(k8s, true); err != nil { return errors.Wrap(err, "wait") } @@ -323,7 +336,7 @@ func (k *KubeadmBootstrapper) RestartCluster(k8s config.KubernetesConfig) error } // DeleteCluster removes the components that were started earlier -func (k *KubeadmBootstrapper) DeleteCluster(k8s config.KubernetesConfig) error { +func (k *Bootstrapper) DeleteCluster(k8s config.KubernetesConfig) error { cmd := fmt.Sprintf("sudo kubeadm reset --force") out, err := k.c.CombinedOutput(cmd) if err != nil { @@ -334,7 +347,7 @@ func (k *KubeadmBootstrapper) DeleteCluster(k8s config.KubernetesConfig) error { } // PullImages downloads images that will be used by RestartCluster -func (k *KubeadmBootstrapper) PullImages(k8s config.KubernetesConfig) error { +func (k *Bootstrapper) PullImages(k8s config.KubernetesConfig) error { version, err := ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") @@ -351,7 +364,7 @@ func (k *KubeadmBootstrapper) PullImages(k8s config.KubernetesConfig) error { } // SetupCerts sets up certificates within the cluster. -func (k *KubeadmBootstrapper) SetupCerts(k8s config.KubernetesConfig) error { +func (k *Bootstrapper) SetupCerts(k8s config.KubernetesConfig) error { return bootstrapper.SetupCerts(k.c, k8s) } @@ -375,7 +388,7 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, extraOpts["network-plugin"] = k8s.NetworkPlugin } - podInfraContainerImage, _ := constants.GetKubeadmImages(k8s.ImageRepository, k8s.KubernetesVersion) + podInfraContainerImage, _ := constants.GetKubeadmCachedImages(k8s.ImageRepository, k8s.KubernetesVersion) if _, ok := extraOpts["pod-infra-container-image"]; !ok && k8s.ImageRepository != "" && podInfraContainerImage != "" { extraOpts["pod-infra-container-image"] = podInfraContainerImage } @@ -407,8 +420,9 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, return b.String(), nil } -func (k *KubeadmBootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { - _, images := constants.GetKubeadmImages(cfg.ImageRepository, cfg.KubernetesVersion) +// UpdateCluster updates the cluster +func (k *Bootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { + _, images := constants.GetKubeadmCachedImages(cfg.ImageRepository, cfg.KubernetesVersion) if cfg.ShouldLoadCachedImages { if err := machine.LoadImages(k.c, images, constants.ImageCacheDir); err != nil { console.Failure("Unable to load cached images: %v", err) @@ -585,7 +599,7 @@ func maybeDownloadAndCache(binary, version string) (string, error) { Mkdirs: download.MkdirAll, } - options.Checksum = constants.GetKubernetesReleaseURLSha1(binary, version) + options.Checksum = constants.GetKubernetesReleaseURLSHA1(binary, version) options.ChecksumHash = crypto.SHA1 console.OutStyle("file-download", "Downloading %s %s", binary, version) diff --git a/pkg/minikube/bootstrapper/kubeadm/versions.go b/pkg/minikube/bootstrapper/kubeadm/versions.go index 0cd243e04067..3706969825ce 100644 --- a/pkg/minikube/bootstrapper/kubeadm/versions.go +++ b/pkg/minikube/bootstrapper/kubeadm/versions.go @@ -60,6 +60,7 @@ func ExtraConfigForComponent(component string, opts util.ExtraOptionSlice, versi return versionedOpts, nil } +// ComponentExtraArgs holds extra args for a component type ComponentExtraArgs struct { Component string Options map[string]string @@ -74,6 +75,7 @@ var componentToKubeadmConfigKey = map[string]string{ Kubelet: "", } +// NewComponentExtraArgs creates a new ComponentExtraArgs func NewComponentExtraArgs(opts util.ExtraOptionSlice, version semver.Version, featureGates string) ([]ComponentExtraArgs, error) { var kubeadmExtraArgs []ComponentExtraArgs for _, extraOpt := range opts { @@ -111,6 +113,7 @@ func NewComponentExtraArgs(opts util.ExtraOptionSlice, version semver.Version, f return kubeadmExtraArgs, nil } +// ParseFeatureArgs parses feature args into extra args func ParseFeatureArgs(featureGates string) (map[string]bool, string, error) { kubeadmFeatureArgs := map[string]bool{} componentFeatureArgs := "" @@ -153,6 +156,7 @@ func Supports(featureName string) bool { return false } +// ParseKubernetesVersion parses the kubernetes version func ParseKubernetesVersion(version string) (semver.Version, error) { // Strip leading 'v' prefix from version for semver parsing v, err := semver.Make(version[1:]) @@ -285,6 +289,7 @@ var versionSpecificOpts = []VersionedExtraOption{ }, } +// VersionIsBetween checks if a version is between (or including) two given versions func VersionIsBetween(version, gte, lte semver.Version) bool { if gte.NE(semver.Version{}) && !version.GTE(gte) { return false @@ -296,6 +301,7 @@ func VersionIsBetween(version, gte, lte semver.Version) bool { return true } +// DefaultOptionsForComponentAndVersion returns the default option for a component and version func DefaultOptionsForComponentAndVersion(component string, version semver.Version) (map[string]string, error) { versionedOpts := map[string]string{} for _, opts := range versionSpecificOpts { diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 116822c0055a..4ad5aa3d2192 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -17,11 +17,9 @@ limitations under the License. package cluster import ( - "bytes" "encoding/json" "flag" "fmt" - "html/template" "net" "os/exec" "regexp" @@ -338,30 +336,6 @@ func GetHostDockerEnv(api libmachine.API) (map[string]string, error) { return envMap, nil } -// MountHost runs the mount command from the 9p client on the VM to the 9p server on the host -func MountHost(api libmachine.API, ip net.IP, path, port, mountVersion string, uid, gid, msize int) error { - host, err := CheckIfHostExistsAndLoad(api, cfg.GetMachineName()) - if err != nil { - return errors.Wrap(err, "Error checking that api exists and loading it") - } - if ip == nil { - ip, err = GetVMHostIP(host) - if err != nil { - return errors.Wrap(err, "Error getting the host IP address to use from within the VM") - } - } - host.RunSSHCommand(GetMountCleanupCommand(path)) - mountCmd, err := GetMountCommand(ip, path, port, mountVersion, uid, gid, msize) - if err != nil { - return errors.Wrap(err, "mount command") - } - _, err = host.RunSSHCommand(mountCmd) - if err != nil { - return errors.Wrap(err, "running mount") - } - return nil -} - // GetVMHostIP gets the ip address to be used for mapping host -> VM and VM -> host func GetVMHostIP(host *host.Host) (net.IP, error) { switch host.DriverName { @@ -411,6 +385,7 @@ func getIPForInterface(name string) (net.IP, error) { return nil, errors.Errorf("Error finding IPV4 address for %s", name) } +// CheckIfHostExistsAndLoad checks if a host exists, and loads it if it does func CheckIfHostExistsAndLoad(api libmachine.API, machineName string) (*host.Host, error) { exists, err := api.Exists(machineName) if err != nil { @@ -427,6 +402,7 @@ func CheckIfHostExistsAndLoad(api libmachine.API, machineName string) (*host.Hos return host, nil } +// CreateSSHShell creates a new SSH shell / client func CreateSSHShell(api libmachine.API, args []string) error { machineName := cfg.GetMachineName() host, err := CheckIfHostExistsAndLoad(api, machineName) @@ -461,38 +437,3 @@ func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) { exit.WithCode(exit.Unavailable, "minikube is not running, so the service cannot be accessed") } } - -func GetMountCleanupCommand(path string) string { - return fmt.Sprintf("sudo umount %s;", path) -} - -var mountTemplate = ` -sudo mkdir -p {{.Path}} || true; -sudo mount -t 9p -o trans=tcp,port={{.Port}},dfltuid={{.UID}},dfltgid={{.GID}},version={{.Version}},msize={{.Msize}} {{.IP}} {{.Path}}; -sudo chmod 775 {{.Path}} || true;` - -func GetMountCommand(ip net.IP, path, port, mountVersion string, uid, gid, msize int) (string, error) { - t := template.Must(template.New("mountCommand").Parse(mountTemplate)) - buf := bytes.Buffer{} - data := struct { - IP string - Path string - Port string - Version string - UID int - GID int - Msize int - }{ - IP: ip.String(), - Path: path, - Port: port, - Version: mountVersion, - UID: uid, - GID: gid, - Msize: msize, - } - if err := t.Execute(&buf, data); err != nil { - return "", err - } - return buf.String(), nil -} diff --git a/pkg/minikube/cluster/cluster_test.go b/pkg/minikube/cluster/cluster_test.go index b3ce79129494..b9d96274f6eb 100644 --- a/pkg/minikube/cluster/cluster_test.go +++ b/pkg/minikube/cluster/cluster_test.go @@ -37,7 +37,7 @@ func (d MockDownloader) CacheMinikubeISOFromURL(isoURL string) error { return ni var defaultMachineConfig = config.MachineConfig{ VMDriver: constants.DefaultVMDriver, - MinikubeISO: constants.DefaultIsoUrl, + MinikubeISO: constants.DefaultISOURL, Downloader: MockDownloader{}, } diff --git a/pkg/minikube/cluster/default_drivers.go b/pkg/minikube/cluster/default_drivers.go index e37e38556133..e45a1014490d 100644 --- a/pkg/minikube/cluster/default_drivers.go +++ b/pkg/minikube/cluster/default_drivers.go @@ -17,6 +17,7 @@ limitations under the License. package cluster import ( + // Import all the default drivers _ "k8s.io/minikube/pkg/minikube/drivers/hyperkit" _ "k8s.io/minikube/pkg/minikube/drivers/hyperv" _ "k8s.io/minikube/pkg/minikube/drivers/kvm" diff --git a/pkg/minikube/cluster/mount.go b/pkg/minikube/cluster/mount.go new file mode 100644 index 000000000000..41181330b880 --- /dev/null +++ b/pkg/minikube/cluster/mount.go @@ -0,0 +1,110 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cluster + +import ( + "fmt" + "os" + "sort" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +// MountConfig defines the options available to the Mount command +type MountConfig struct { + // Type is the filesystem type (Typically 9p) + Type string + // UID is the User ID which this path will be mounted as + UID int + // GID is the Group ID which this path will be mounted as + GID int + // Version is the 9P protocol version. Valid options: 9p2000, 9p200.u, 9p2000.L + Version string + // MSize is the number of bytes to use for 9p packet payload + MSize int + // Port is the port to connect to on the host + Port int + // Mode is the file permissions to set the mount to (octals) + Mode os.FileMode + // Extra mount options. See https://www.kernel.org/doc/Documentation/filesystems/9p.txt + Options map[string]string +} + +// hostRunner is the subset of host.Host used for mounting +type hostRunner interface { + RunSSHCommand(cmd string) (string, error) +} + +// Mount runs the mount command from the 9p client on the VM to the 9p server on the host +func Mount(h hostRunner, source string, target string, c *MountConfig) error { + if err := Unmount(h, target); err != nil { + return errors.Wrap(err, "umount") + } + + cmd := fmt.Sprintf("sudo mkdir -m %o -p %s && %s", c.Mode, target, mntCmd(source, target, c)) + out, err := h.RunSSHCommand(cmd) + if err != nil { + return errors.Wrap(err, out) + } + return nil +} + +// mntCmd returns a mount command based on a config. +func mntCmd(source string, target string, c *MountConfig) string { + options := map[string]string{ + "dfltgid": strconv.Itoa(c.GID), + "dfltuid": strconv.Itoa(c.UID), + } + if c.Port != 0 { + options["port"] = strconv.Itoa(c.Port) + } + if c.Version != "" { + options["version"] = c.Version + } + if c.MSize != 0 { + options["msize"] = strconv.Itoa(c.MSize) + } + + // Copy in all of the user-supplied keys and values + for k, v := range c.Options { + options[k] = v + } + + // Convert everything into a sorted list for better test results + opts := []string{} + for k, v := range options { + // Mount option with no value, such as "noextend" + if v == "" { + opts = append(opts, k) + continue + } + opts = append(opts, fmt.Sprintf("%s=%s", k, v)) + } + sort.Strings(opts) + return fmt.Sprintf("sudo mount -t %s -o %s %s %s", c.Type, strings.Join(opts, ","), source, target) +} + +// Unmount unmounts a path +func Unmount(h hostRunner, target string) error { + out, err := h.RunSSHCommand(fmt.Sprintf("findmnt -T %s && sudo umount %s || true", target, target)) + if err != nil { + return errors.Wrap(err, out) + } + return nil +} diff --git a/pkg/minikube/cluster/mount_test.go b/pkg/minikube/cluster/mount_test.go new file mode 100644 index 000000000000..cd10d1d10461 --- /dev/null +++ b/pkg/minikube/cluster/mount_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cluster + +import ( + "os" + "testing" + + "github.com/google/go-cmp/cmp" +) + +type mockMountHost struct { + cmds []string + T *testing.T +} + +func NewMockMountHost(t *testing.T) *mockMountHost { + return &mockMountHost{ + T: t, + cmds: []string{}, + } +} + +func (m *mockMountHost) RunSSHCommand(cmd string) (string, error) { + m.cmds = append(m.cmds, cmd) + return "", nil +} + +func TestMount(t *testing.T) { + var tests = []struct { + name string + source string + target string + cfg *MountConfig + want []string + }{ + { + name: "simple", + source: "src", + target: "target", + cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0700)}, + want: []string{ + "findmnt -T target && sudo umount target || true", + "sudo mkdir -m 700 -p target && sudo mount -t 9p -o dfltgid=0,dfltuid=0 src target", + }, + }, + { + name: "everything", + source: "10.0.0.1", + target: "/target", + cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0777), UID: 82, GID: 72, Version: "9p2000.u", Options: map[string]string{ + "noextend": "", + "cache": "fscache", + }}, + want: []string{ + "findmnt -T /target && sudo umount /target || true", + "sudo mkdir -m 777 -p /target && sudo mount -t 9p -o cache=fscache,dfltgid=72,dfltuid=82,noextend,version=9p2000.u 10.0.0.1 /target", + }, + }, + { + name: "version-conflict", + source: "src", + target: "tgt", + cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0700), Version: "9p2000.u", Options: map[string]string{ + "version": "9p2000.L", + }}, + want: []string{ + "findmnt -T tgt && sudo umount tgt || true", + "sudo mkdir -m 700 -p tgt && sudo mount -t 9p -o dfltgid=0,dfltuid=0,version=9p2000.L src tgt", + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + h := NewMockMountHost(t) + err := Mount(h, tc.source, tc.target, tc.cfg) + if err != nil { + t.Fatalf("Mount(%s, %s, %+v): %v", tc.source, tc.target, tc.cfg, err) + } + if diff := cmp.Diff(h.cmds, tc.want); diff != "" { + t.Errorf("command diff (-want +got): %s", diff) + } + }) + } +} + +func TestUnmount(t *testing.T) { + h := NewMockMountHost(t) + err := Unmount(h, "/mnt") + if err != nil { + t.Fatalf("Unmount(/mnt): %v", err) + } + + want := []string{"findmnt -T /mnt && sudo umount /mnt || true"} + if diff := cmp.Diff(h.cmds, want); diff != "" { + t.Errorf("command diff (-want +got): %s", diff) + } +} diff --git a/pkg/minikube/config/config.go b/pkg/minikube/config/config.go index 6c16c68a6f27..d78d3c13b6b1 100644 --- a/pkg/minikube/config/config.go +++ b/pkg/minikube/config/config.go @@ -30,19 +30,30 @@ import ( ) const ( - WantUpdateNotification = "WantUpdateNotification" - ReminderWaitPeriodInHours = "ReminderWaitPeriodInHours" - WantReportError = "WantReportError" - WantReportErrorPrompt = "WantReportErrorPrompt" - WantKubectlDownloadMsg = "WantKubectlDownloadMsg" - WantNoneDriverWarning = "WantNoneDriverWarning" - MachineProfile = "profile" - ShowDriverDeprecationNotification = "ShowDriverDeprecationNotification" + // WantUpdateNotification is the key for WantUpdateNotification + WantUpdateNotification = "WantUpdateNotification" + // ReminderWaitPeriodInHours is the key for WantUpdateNotification + ReminderWaitPeriodInHours = "ReminderWaitPeriodInHours" + // WantReportError is the key for WantReportError + WantReportError = "WantReportError" + // WantReportErrorPrompt is the key for WantReportErrorPrompt + WantReportErrorPrompt = "WantReportErrorPrompt" + // WantKubectlDownloadMsg is the key for WantKubectlDownloadMsg + WantKubectlDownloadMsg = "WantKubectlDownloadMsg" + // WantNoneDriverWarning is the key for WantNoneDriverWarning + WantNoneDriverWarning = "WantNoneDriverWarning" + // MachineProfile is the key for MachineProfile + MachineProfile = "profile" + // ShowDriverDeprecationNotification is the key for ShowDriverDeprecationNotification + ShowDriverDeprecationNotification = "ShowDriverDeprecationNotification" + // ShowBootstrapperDeprecationNotification is the key for ShowBootstrapperDeprecationNotification ShowBootstrapperDeprecationNotification = "ShowBootstrapperDeprecationNotification" ) +// MinikubeConfig represents minikube config type MinikubeConfig map[string]interface{} +// Get gets a named value from config func Get(name string) (string, error) { m, err := ReadConfig() if err != nil { @@ -103,6 +114,7 @@ type Loader interface { type simpleConfigLoader struct{} +// DefaultLoader is the default config loader var DefaultLoader Loader = &simpleConfigLoader{} func (c *simpleConfigLoader) LoadConfigFromFile(profile string) (*Config, error) { diff --git a/pkg/minikube/console/style.go b/pkg/minikube/console/style.go index 366ad2769963..1a7f45636f29 100644 --- a/pkg/minikube/console/style.go +++ b/pkg/minikube/console/style.go @@ -93,8 +93,11 @@ var styles = map[string]style{ "verifying-noline": {Prefix: "🤔 ", OmitNewline: true}, "kubectl": {Prefix: "💗 ", LowPrefix: "+ "}, "meh": {Prefix: "🙄 ", LowPrefix: "? "}, - "embarassed": {Prefix: "🤦 ", LowPrefix: "* "}, + "embarrassed": {Prefix: "🤦 ", LowPrefix: "* "}, "tip": {Prefix: "💡 ", LowPrefix: "i "}, + "unmount": {Prefix: "🔥 ", LowPrefix: "x "}, + "mount-options": {Prefix: "💾 ", LowPrefix: "o "}, + "fileserver": {Prefix: "🚀 ", LowPrefix: "@ ", OmitNewline: true}, } // Add a prefix to a string diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index f9997172051a..a31f657f3e73 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -37,9 +37,10 @@ const ( ClusterDNSDomain = "cluster.local" ) +// MinikubeHome is the name of the minikube home directory variable. const MinikubeHome = "MINIKUBE_HOME" -// Minipath is the path to the user's minikube dir +// GetMinipath returns the path to the user's minikube dir func GetMinipath() string { if os.Getenv(MinikubeHome) == "" { return DefaultMinipath @@ -65,6 +66,7 @@ var SupportedVMDrivers = [...]string{ "none", } +// DefaultMinipath is the default Minikube path (under the home directory) var DefaultMinipath = filepath.Join(homedir.HomeDir(), ".minikube") // KubeconfigPath is the path to the Kubernetes client config @@ -85,12 +87,13 @@ const DefaultMachineName = "minikube" // DefaultNodeName is the default name for the kubeadm node within the VM const DefaultNodeName = "minikube" -// The name of the default storage class provisioner +// DefaultStorageClassProvisioner is the name of the default storage class provisioner const DefaultStorageClassProvisioner = "standard" -// Used to modify the cache field in the config file +// Cache is used to modify the cache field in the config file const Cache = "cache" +// TunnelRegistryPath returns the path to the runnel registry file func TunnelRegistryPath() string { return filepath.Join(GetMinipath(), "tunnels.json") } @@ -102,37 +105,61 @@ func MakeMiniPath(fileName ...string) string { return filepath.Join(args...) } +// MountProcessFileName is the filename of the mount process var MountProcessFileName = ".mount-process" const ( - DefaultKeepContext = false - ShaSuffix = ".sha256" - DefaultMemory = 2048 - DefaultCPUS = 2 - DefaultDiskSize = "20g" - MinimumDiskSizeMB = 2000 - DefaultVMDriver = "virtualbox" + // DefaultKeepContext is if we should keep context by default + DefaultKeepContext = false + // SHASuffix is the suffix of a SHA-256 checksum file + SHASuffix = ".sha256" + // DefaultMemory is the default memory of a host, in megabytes + DefaultMemory = 2048 + // DefaultCPUS is the default number of cpus of a host + DefaultCPUS = 2 + // DefaultDiskSize is the default disk image size, parseable + DefaultDiskSize = "20g" + // MinimumDiskSizeMB is the minimum disk image size, in megabytes + MinimumDiskSizeMB = 2000 + // DefaultVMDriver is the default virtual machine driver name + DefaultVMDriver = "virtualbox" + // DefaultStatusFormat is the default format of a host DefaultStatusFormat = `host: {{.Host}} kubelet: {{.Kubelet}} apiserver: {{.ApiServer}} kubectl: {{.Kubeconfig}} ` - DefaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n" - DefaultConfigViewFormat = "- {{.ConfigKey}}: {{.ConfigValue}}\n" - DefaultCacheListFormat = "{{.CacheImage}}\n" - GithubMinikubeReleasesURL = "https://storage.googleapis.com/minikube/releases.json" - DefaultWait = 20 - DefaultInterval = 6 - DefaultK8sClientTimeout = 60 * time.Second + // DefaultAddonListFormat is the default format of addon list + DefaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n" + // DefaultConfigViewFormat is the default format of config view + DefaultConfigViewFormat = "- {{.ConfigKey}}: {{.ConfigValue}}\n" + // DefaultCacheListFormat is the default format of cache list + DefaultCacheListFormat = "{{.CacheImage}}\n" + // GithubMinikubeReleasesURL is the URL of the minikube github releases JSON file + GithubMinikubeReleasesURL = "https://storage.googleapis.com/minikube/releases.json" + // DefaultWait is the default wait time, in seconds + DefaultWait = 20 + // DefaultInterval is the default interval, in seconds + DefaultInterval = 6 + // DefaultK8sClientTimeout is the default kubernetes client timeout + DefaultK8sClientTimeout = 60 * time.Second + // DefaultClusterBootstrapper is the default cluster bootstrapper DefaultClusterBootstrapper = "kubeadm" ) -var DefaultIsoUrl = fmt.Sprintf("https://storage.googleapis.com/%s/minikube-%s.iso", minikubeVersion.GetIsoPath(), minikubeVersion.GetIsoVersion()) -var DefaultIsoShaUrl = DefaultIsoUrl + ShaSuffix +// DefaultISOURL is the default location of the minikube.iso file +var DefaultISOURL = fmt.Sprintf("https://storage.googleapis.com/%s/minikube-%s.iso", minikubeVersion.GetISOPath(), minikubeVersion.GetISOVersion()) +// DefaultISOSHAURL is the default location of the minikube.iso.sha256 file +var DefaultISOSHAURL = DefaultISOURL + SHASuffix + +// DefaultKubernetesVersion is the default kubernetes version var DefaultKubernetesVersion = "v1.13.4" +// ConfigFilePath is the path of the config directory var ConfigFilePath = MakeMiniPath("config") + +// ConfigFile is the path of the config file var ConfigFile = MakeMiniPath("config", "config.json") // GetProfileFile returns the Minikube profile config file @@ -143,40 +170,62 @@ func GetProfileFile(profile string) string { // DockerAPIVersion is the API version implemented by Docker running in the minikube VM. const DockerAPIVersion = "1.35" +// ReportingURL is the URL for reporting a minikube error const ReportingURL = "https://clouderrorreporting.googleapis.com/v1beta1/projects/k8s-minikube/events:report?key=AIzaSyACUwzG0dEPcl-eOgpDKnyKoUFgHdfoFuA" +// AddonsPath is the default path of the addons configuration const AddonsPath = "/etc/kubernetes/addons" + +// FilesPath is the default path of files const FilesPath = "/files" const ( - KubeletServiceFile = "/lib/systemd/system/kubelet.service" - KubeletSystemdConfFile = "/etc/systemd/system/kubelet.service.d/10-kubeadm.conf" - KubeadmConfigFile = "/var/lib/kubeadm.yaml" - DefaultCNIConfigPath = "/etc/cni/net.d/k8s.conf" + // KubeletServiceFile is the path to the kubelet systemd service + KubeletServiceFile = "/lib/systemd/system/kubelet.service" + // KubeletSystemdConfFile is the path to the kubelet systemd configuration + KubeletSystemdConfFile = "/etc/systemd/system/kubelet.service.d/10-kubeadm.conf" + // KubeadmConfigFile is the path to the kubeadm configuration + KubeadmConfigFile = "/var/lib/kubeadm.yaml" + // DefaultCNIConfigPath is the path to the CNI configuration + DefaultCNIConfigPath = "/etc/cni/net.d/k8s.conf" + // DefaultRktNetConfigPath is the path to the rkt net configuration DefaultRktNetConfigPath = "/etc/rkt/net.d/k8s.conf" ) const ( - DefaultUfsPort = "5640" - DefaultUfsDebugLvl = 0 + // DefaultUfsPort is the default port of UFS + DefaultUfsPort = "5640" + // DefaultUfsDebugLvl is the default debug level of UFS + DefaultUfsDebugLvl = 0 + // DefaultMountEndpoint is the default mount endpoint DefaultMountEndpoint = "/minikube-host" - DefaultMsize = 262144 + // DefaultMsize is the default number of bytes to use for 9p packet payload + DefaultMsize = 262144 + // DefaultMountVersion is the default 9p version to use for mount DefaultMountVersion = "9p2000.L" ) +// GetKubernetesReleaseURL gets the location of a kubernetes client func GetKubernetesReleaseURL(binaryName, version string) string { return fmt.Sprintf("https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/%s/%s", version, runtime.GOARCH, binaryName) } -func GetKubernetesReleaseURLSha1(binaryName, version string) string { +// GetKubernetesReleaseURLSHA1 gets the location of a kubernetes client checksum +func GetKubernetesReleaseURLSHA1(binaryName, version string) string { return fmt.Sprintf("%s.sha1", GetKubernetesReleaseURL(binaryName, version)) } +// IsMinikubeChildProcess is the name of "is minikube child process" variable const IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS" + +// DriverNone is the none driver const DriverNone = "none" + +// FileScheme is the file scheme const FileScheme = "file" -func GetKubeadmImages(imageRepository string, kubernetesVersionStr string) (string, []string) { +// GetKubeadmCachedImages gets the images to cache for kubeadm for a version +func GetKubeadmCachedImages(imageRepository string, kubernetesVersionStr string) (string, []string) { minikubeRepository := imageRepository if imageRepository == "" { imageRepository = "k8s.gcr.io" @@ -301,6 +350,7 @@ func GetKubeadmImages(imageRepository string, kubernetesVersionStr string) (stri return podInfraContainerImage, images } +// ImageCacheDir is the path to the image cache directory var ImageCacheDir = MakeMiniPath("cache", "images") const ( diff --git a/pkg/minikube/constants/constants_linux.go b/pkg/minikube/constants/constants_linux.go index 1df7788d30ac..a5419b777190 100644 --- a/pkg/minikube/constants/constants_linux.go +++ b/pkg/minikube/constants/constants_linux.go @@ -22,4 +22,5 @@ import ( "k8s.io/client-go/util/homedir" ) +// DefaultMountDir is the default mount dir var DefaultMountDir = homedir.HomeDir() diff --git a/pkg/minikube/cruntime/docker.go b/pkg/minikube/cruntime/docker.go index 5ba542d65b89..e8a0a9b39b81 100644 --- a/pkg/minikube/cruntime/docker.go +++ b/pkg/minikube/cruntime/docker.go @@ -24,6 +24,7 @@ import ( "github.com/golang/glog" ) +// KubernetesContainerPrefix is the prefix of each kubernetes container const KubernetesContainerPrefix = "k8s_" // Docker contains Docker runtime state diff --git a/pkg/minikube/exit/exit.go b/pkg/minikube/exit/exit.go index 3b5508d983f6..afff9bf0c83a 100644 --- a/pkg/minikube/exit/exit.go +++ b/pkg/minikube/exit/exit.go @@ -30,13 +30,14 @@ import ( // Exit codes based on sysexits(3) const ( Failure = 1 // Failure represents a general failure code + Interrupted = 2 // Ctrl-C (SIGINT) BadUsage = 64 // Usage represents an incorrect command line Data = 65 // Data represents incorrect data supplied by the user NoInput = 66 // NoInput represents that the input file did not exist or was not readable Unavailable = 69 // Unavailable represents when a service was unavailable Software = 70 // Software represents an internal software error. IO = 74 // IO represents an I/O error - Config = 78 // Config represents an unconfigured or miscon­figured state + Config = 78 // Config represents an unconfigured or misconfigured state Permissions = 77 // Permissions represents a permissions error // MaxProblems controls the number of problems to show for each source diff --git a/pkg/minikube/logs/logs.go b/pkg/minikube/logs/logs.go index a06f383cd217..83e3f5c55f6f 100644 --- a/pkg/minikube/logs/logs.go +++ b/pkg/minikube/logs/logs.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// package logs are convenience methods for fetching logs from a minikube cluster +// Package logs are convenience methods for fetching logs from a minikube cluster package logs import ( diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index 2afcc6052218..7866bfbf7d0e 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -48,6 +48,7 @@ var getWindowsVolumeName = getWindowsVolumeNameCmd // loadImageLock is used to serialize image loads to avoid overloading the guest VM var loadImageLock sync.Mutex +// CacheImagesForBootstrapper will cache images for a bootstrapper func CacheImagesForBootstrapper(imageRepository string, version string, clusterBootstrapper string) error { images := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper) @@ -83,6 +84,7 @@ func CacheImages(images []string, cacheDir string) error { return nil } +// LoadImages loads previously cached images into the container runtime func LoadImages(cmd bootstrapper.CommandRunner, images []string, cacheDir string) error { var g errgroup.Group // Load profile cluster config from file @@ -108,6 +110,7 @@ func LoadImages(cmd bootstrapper.CommandRunner, images []string, cacheDir string return nil } +// CacheAndLoadImages caches and loads images func CacheAndLoadImages(images []string) error { if err := CacheImages(images, constants.ImageCacheDir); err != nil { return err @@ -195,6 +198,7 @@ func getWindowsVolumeNameCmd(d string) (string, error) { return vname, nil } +// LoadFromCacheBlocking loads images from cache, blocking until loaded func LoadFromCacheBlocking(cr bootstrapper.CommandRunner, k8s config.KubernetesConfig, src string) error { glog.Infoln("Loading image from cache at ", src) filename := filepath.Base(src) @@ -231,6 +235,7 @@ func LoadFromCacheBlocking(cr bootstrapper.CommandRunner, k8s config.KubernetesC return nil } +// DeleteFromImageCacheDir deletes images from the cache func DeleteFromImageCacheDir(images []string) error { for _, image := range images { path := filepath.Join(constants.ImageCacheDir, image) @@ -282,6 +287,7 @@ func getDstPath(image, dst string) (string, error) { return dst, nil } +// CacheImage caches an image func CacheImage(image, dst string) error { glog.Infof("Attempting to cache image: %s at %s\n", image, dst) if _, err := os.Stat(dst); err == nil { diff --git a/pkg/minikube/machine/client.go b/pkg/minikube/machine/client.go index 2ae8dda5f3c9..b238665e631d 100644 --- a/pkg/minikube/machine/client.go +++ b/pkg/minikube/machine/client.go @@ -48,6 +48,7 @@ import ( "k8s.io/minikube/pkg/provision" ) +// NewRPCClient gets a new client. func NewRPCClient(storePath, certsDir string) libmachine.API { c := libmachine.NewClient(storePath, certsDir) c.SSHClientType = ssh.Native @@ -76,6 +77,7 @@ type LocalClient struct { legacyClient libmachine.API } +// NewHost creates a new Host func (api *LocalClient) NewHost(driverName string, rawDriver []byte) (*host.Host, error) { var def registry.DriverDef var err error @@ -116,6 +118,7 @@ func (api *LocalClient) NewHost(driverName string, rawDriver []byte) (*host.Host }, nil } +// Load a new client, creating driver func (api *LocalClient) Load(name string) (*host.Host, error) { h, err := api.Filestore.Load(name) if err != nil { @@ -133,6 +136,7 @@ func (api *LocalClient) Load(name string) (*host.Host, error) { return h, json.Unmarshal(h.RawDriver, h.Driver) } +// Close closes the client func (api *LocalClient) Close() error { if api.legacyClient != nil { return api.legacyClient.Close() @@ -152,6 +156,7 @@ func CommandRunner(h *host.Host) (bootstrapper.CommandRunner, error) { return bootstrapper.NewSSHRunner(client), nil } +// Create creates the host func (api *LocalClient) Create(h *host.Host) error { if def, err := registry.Driver(h.DriverName); err != nil { return err @@ -211,6 +216,7 @@ func (api *LocalClient) Create(h *host.Host) error { return nil } +// StartDriver starts the driver func StartDriver() { cert.SetCertGenerator(&CertGenerator{}) check.DefaultConnChecker = &ConnChecker{} @@ -221,9 +227,11 @@ func StartDriver() { localbinary.CurrentBinaryIsDockerMachine = true } +// ConnChecker can check the connection type ConnChecker struct { } +// Check checks the connection func (cc *ConnChecker) Check(h *host.Host, swarm bool) (string, *auth.Options, error) { authOptions := h.AuthOptions() dockerHost, err := h.Driver.GetURL() diff --git a/pkg/minikube/notify/notify.go b/pkg/minikube/notify/notify.go index 1e59916f71fe..f70f9c9e7a38 100644 --- a/pkg/minikube/notify/notify.go +++ b/pkg/minikube/notify/notify.go @@ -42,10 +42,12 @@ var ( lastUpdateCheckFilePath = constants.MakeMiniPath("last_update_check") ) +// MaybePrintUpdateTextFromGithub prints update text if needed, from github func MaybePrintUpdateTextFromGithub(output io.Writer) { MaybePrintUpdateText(output, constants.GithubMinikubeReleasesURL, lastUpdateCheckFilePath) } +// MaybePrintUpdateText prints update text if needed func MaybePrintUpdateText(output io.Writer, url string, lastUpdatePath string) { if !shouldCheckURLVersion(lastUpdatePath) { return @@ -80,14 +82,16 @@ func shouldCheckURLVersion(filePath string) bool { return time.Since(lastUpdateTime).Hours() >= viper.GetFloat64(config.ReminderWaitPeriodInHours) } +// Release represents a release type Release struct { Name string Checksums map[string]string } +// Releases represents several release type Releases []Release -func getJson(url string, target *Releases) error { +func getJSON(url string, target *Releases) error { client := &http.Client{} req, err := http.NewRequest("GET", url, nil) @@ -116,10 +120,11 @@ func getLatestVersionFromURL(url string) (semver.Version, error) { return semver.Make(strings.TrimPrefix(r[0].Name, version.VersionPrefix)) } +// GetAllVersionsFromURL get all versions from a JSON URL func GetAllVersionsFromURL(url string) (Releases, error) { var releases Releases glog.Info("Checking for updates...") - if err := getJson(url, &releases); err != nil { + if err := getJSON(url, &releases); err != nil { return releases, errors.Wrap(err, "Error getting json from minikube version url") } if len(releases) == 0 { diff --git a/pkg/minikube/registry/registry.go b/pkg/minikube/registry/registry.go index 526153e55b4f..f3ac464b14fd 100644 --- a/pkg/minikube/registry/registry.go +++ b/pkg/minikube/registry/registry.go @@ -89,14 +89,17 @@ var ( registry = createRegistry() ) +// ListDrivers lists all drivers in registry func ListDrivers() []DriverDef { return registry.List() } +// Register registers driver func Register(driver DriverDef) error { return registry.Register(driver) } +// Driver gets a named driver func Driver(name string) (DriverDef, error) { return registry.Driver(name) } diff --git a/pkg/minikube/service/service.go b/pkg/minikube/service/service.go index 12e6d4a028f3..0db95eca038d 100644 --- a/pkg/minikube/service/service.go +++ b/pkg/minikube/service/service.go @@ -43,19 +43,23 @@ import ( "k8s.io/minikube/pkg/util" ) +// K8sClient represents a kubernetes client type K8sClient interface { GetCoreClient() (corev1.CoreV1Interface, error) GetClientset(timeout time.Duration) (*kubernetes.Clientset, error) } +// K8sClientGetter can get a K8sClient type K8sClientGetter struct{} +// K8s is the current K8sClient var K8s K8sClient func init() { K8s = &K8sClientGetter{} } +// GetCoreClient returns a core client func (k *K8sClientGetter) GetCoreClient() (corev1.CoreV1Interface, error) { client, err := k.GetClientset(constants.DefaultK8sClientTimeout) if err != nil { @@ -64,6 +68,7 @@ func (k *K8sClientGetter) GetCoreClient() (corev1.CoreV1Interface, error) { return client.Core(), nil } +// GetClientset returns a clientset func (*K8sClientGetter) GetClientset(timeout time.Duration) (*kubernetes.Clientset, error) { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() profile := viper.GetString(config.MachineProfile) @@ -87,15 +92,17 @@ func (*K8sClientGetter) GetClientset(timeout time.Duration) (*kubernetes.Clients return client, nil } +// URL represents service URL type URL struct { Namespace string Name string URLs []string } +// URLs represents a list of URL type URLs []URL -// Returns all the node port URLs for every service in a particular namespace +// GetServiceURLs returns all the node port URLs for every service in a particular namespace // Accepts a template for formatting func GetServiceURLs(api libmachine.API, namespace string, t *template.Template) (URLs, error) { host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) @@ -132,7 +139,7 @@ func GetServiceURLs(api libmachine.API, namespace string, t *template.Template) return serviceURLs, nil } -// Returns all the node ports for a service in a namespace +// GetServiceURLsForService returns all the node ports for a service in a namespace // with optional formatting func GetServiceURLsForService(api libmachine.API, namespace, service string, t *template.Template) ([]string, error) { host, err := cluster.CheckIfHostExistsAndLoad(api, config.GetMachineName()) @@ -210,6 +217,7 @@ func CheckService(namespace string, service string) error { return nil } +// OptionallyHTTPSFormattedURLString returns a formatted URL string, optionally HTTPS func OptionallyHTTPSFormattedURLString(bareURLString string, https bool) (string, bool) { httpsFormattedString := bareURLString isHTTPSchemedURL := false @@ -225,6 +233,7 @@ func OptionallyHTTPSFormattedURLString(bareURLString string, https bool) (string return httpsFormattedString, isHTTPSchemedURL } +// WaitAndMaybeOpenService waits for a service, and opens it when running func WaitAndMaybeOpenService(api libmachine.API, namespace string, service string, urlTemplate *template.Template, urlMode bool, https bool, wait int, interval int) error { if err := util.RetryAfter(wait, func() error { return CheckService(namespace, service) }, time.Duration(interval)*time.Second); err != nil { @@ -248,6 +257,7 @@ func WaitAndMaybeOpenService(api libmachine.API, namespace string, service strin return nil } +// GetServiceListByLabel returns a ServiceList by label func GetServiceListByLabel(namespace string, key string, value string) (*v1.ServiceList, error) { client, err := K8s.GetCoreClient() if err != nil { diff --git a/pkg/minikube/tests/api_mock.go b/pkg/minikube/tests/api_mock.go index 1dc69609ef6c..9c6d87a8e5bd 100644 --- a/pkg/minikube/tests/api_mock.go +++ b/pkg/minikube/tests/api_mock.go @@ -33,6 +33,7 @@ type MockAPI struct { SaveCalled bool } +// NewMockAPI returns a new MockAPI func NewMockAPI() *MockAPI { m := MockAPI{ FakeStore: FakeStore{ diff --git a/pkg/minikube/tests/dir_utils.go b/pkg/minikube/tests/dir_utils.go index 0f6cb0710e7f..c85915ec329b 100644 --- a/pkg/minikube/tests/dir_utils.go +++ b/pkg/minikube/tests/dir_utils.go @@ -25,6 +25,7 @@ import ( "k8s.io/minikube/pkg/minikube/constants" ) +// MakeTempDir creates the temp dir and returns the path func MakeTempDir() string { tempDir, err := ioutil.TempDir("", "minipath") if err != nil { diff --git a/pkg/minikube/tests/driver_mock.go b/pkg/minikube/tests/driver_mock.go index 6ffe72bfdaf8..9f5966ef515b 100644 --- a/pkg/minikube/tests/driver_mock.go +++ b/pkg/minikube/tests/driver_mock.go @@ -39,6 +39,7 @@ func (driver *MockDriver) Create() error { return nil } +// GetIP returns the IP address func (driver *MockDriver) GetIP() (string, error) { if driver.IP != "" { return driver.IP, nil @@ -54,6 +55,7 @@ func (driver *MockDriver) GetCreateFlags() []mcnflag.Flag { return []mcnflag.Flag{} } +// GetSSHPort returns the SSH port func (driver *MockDriver) GetSSHPort() (int, error) { return driver.Port, nil } @@ -66,7 +68,7 @@ func (driver *MockDriver) GetSSHHostname() (string, error) { return "localhost", nil } -// GetSSHHostname returns the hostname for SSH +// GetSSHKeyPath returns the key path for SSH func (driver *MockDriver) GetSSHKeyPath() string { return driver.BaseDriver.SSHKeyPath } diff --git a/pkg/minikube/tests/fake_store.go b/pkg/minikube/tests/fake_store.go index f8226da787bb..7eb9a591103d 100644 --- a/pkg/minikube/tests/fake_store.go +++ b/pkg/minikube/tests/fake_store.go @@ -21,7 +21,7 @@ import ( "github.com/docker/machine/libmachine/mcnerror" ) -//implements persist.Store from libmachine +// FakeStore implements persist.Store from libmachine type FakeStore struct { Hosts map[string]*host.Host } @@ -32,6 +32,7 @@ func (s *FakeStore) Exists(name string) (bool, error) { return ok, nil } +// List returns the list of hosts. func (s *FakeStore) List() ([]string, error) { hostNames := []string{} for h := range s.Hosts { diff --git a/pkg/minikube/tests/host_mock.go b/pkg/minikube/tests/host_mock.go index be9f584027b9..dc25df43b7f4 100644 --- a/pkg/minikube/tests/host_mock.go +++ b/pkg/minikube/tests/host_mock.go @@ -32,6 +32,7 @@ type MockHost struct { Driver drivers.Driver } +// NewMockHost creates a new MockHost func NewMockHost() *MockHost { return &MockHost{ CommandOutput: make(map[string]string), @@ -40,6 +41,7 @@ func NewMockHost() *MockHost { } } +// RunSSHCommand runs a SSH command, returning output func (m MockHost) RunSSHCommand(cmd string) (string, error) { m.Commands[cmd] = 1 output, ok := m.CommandOutput[cmd] diff --git a/pkg/minikube/tests/provision_mock.go b/pkg/minikube/tests/provision_mock.go index 0ba4506d3396..61578aa8a5a2 100644 --- a/pkg/minikube/tests/provision_mock.go +++ b/pkg/minikube/tests/provision_mock.go @@ -26,7 +26,7 @@ import ( "github.com/docker/machine/libmachine/swarm" ) -// Provisioner defines distribution specific actions +// MockProvisioner defines distribution specific actions type MockProvisioner struct { Provisioned bool } @@ -35,69 +35,86 @@ func (provisioner *MockProvisioner) String() string { return "mock" } +// Service performs an action for a service func (provisioner *MockProvisioner) Service(name string, action serviceaction.ServiceAction) error { return nil } +// Package performs an action for a package func (provisioner *MockProvisioner) Package(name string, action pkgaction.PackageAction) error { return nil } +// Hostname returns the hostname func (provisioner *MockProvisioner) Hostname() (string, error) { return "mockhostname", nil } +// SetHostname sets the hostname func (provisioner *MockProvisioner) SetHostname(hostname string) error { return nil } +// GetDockerOptionsDir gets Docker options dir func (provisioner *MockProvisioner) GetDockerOptionsDir() string { return "/mockdirectory" } +// GetAuthOptions returns a the auth.Options func (provisioner *MockProvisioner) GetAuthOptions() auth.Options { return auth.Options{} } +// GenerateDockerOptions generates Docker options func (provisioner *MockProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) { return &provision.DockerOptions{}, nil } +// CompatibleWithHost checks if provisioner is compatible with host func (provisioner *MockProvisioner) CompatibleWithHost() bool { return true } +// SetOsReleaseInfo sets the os-release info func (provisioner *MockProvisioner) SetOsReleaseInfo(info *provision.OsRelease) { } +// GetOsReleaseInfo gets the os-release info func (provisioner *MockProvisioner) GetOsReleaseInfo() (*provision.OsRelease, error) { return nil, nil } +// AttemptIPContact attemps to contact an IP and port func (provisioner *MockProvisioner) AttemptIPContact(dockerPort int) { } +// Provision provisions the machine func (provisioner *MockProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error { provisioner.Provisioned = true return nil } +// SSHCommand runs a SSH command func (provisioner *MockProvisioner) SSHCommand(args string) (string, error) { return "", nil } +// GetDriver gets the driver func (provisioner *MockProvisioner) GetDriver() drivers.Driver { return &MockDriver{} } +// GetSwarmOptions gets the swarm.Options func (provisioner *MockProvisioner) GetSwarmOptions() swarm.Options { return swarm.Options{} } +// MockDetector can detect MockProvisioner type MockDetector struct { Provisioner *MockProvisioner } +// DetectProvisioner detects a provisioner func (m *MockDetector) DetectProvisioner(d drivers.Driver) (provision.Provisioner, error) { return m.Provisioner, nil } diff --git a/pkg/minikube/tests/ssh_mock.go b/pkg/minikube/tests/ssh_mock.go index 2e2d0bdf83cf..e6447786b1ae 100644 --- a/pkg/minikube/tests/ssh_mock.go +++ b/pkg/minikube/tests/ssh_mock.go @@ -154,10 +154,12 @@ func (s *SSHServer) Start() (int, error) { return port, nil } +// SetCommandToOutput sets command to output func (s *SSHServer) SetCommandToOutput(cmdToOutput map[string]string) { s.commandToOutput.Store(cmdToOutput) } +// GetCommandToOutput gets command to output func (s *SSHServer) GetCommandToOutput(cmd string) (string, error) { cmdMap := s.commandToOutput.Load().(map[string]string) val, ok := cmdMap[cmd] @@ -167,6 +169,7 @@ func (s *SSHServer) GetCommandToOutput(cmd string) (string, error) { return val, nil } +// SetSessionRequested sets session requested func (s *SSHServer) SetSessionRequested(b bool) { var i int32 if b { @@ -175,6 +178,7 @@ func (s *SSHServer) SetSessionRequested(b bool) { atomic.StoreInt32(&s.hadASessionRequested, i) } +// IsSessionRequested gcode ets session requested func (s *SSHServer) IsSessionRequested() bool { return atomic.LoadInt32(&s.hadASessionRequested) != 0 } diff --git a/pkg/minikube/tunnel/registry.go b/pkg/minikube/tunnel/registry.go index e4ccde963b93..3e6d9f353ffe 100644 --- a/pkg/minikube/tunnel/registry.go +++ b/pkg/minikube/tunnel/registry.go @@ -28,6 +28,8 @@ import ( // There is one tunnel registry per user, shared across multiple vms. // It can register, list and check for existing and running tunnels + +// ID represents a registry ID type ID struct { //Route is the key Route *Route @@ -36,6 +38,7 @@ type ID struct { Pid int } +// Equal checks if two ID are equal func (t *ID) Equal(other *ID) bool { return t.Route.Equal(other.Route) && t.MachineName == other.MachineName && @@ -70,7 +73,7 @@ func (r *persistentRegistry) IsAlreadyDefinedAndRunning(tunnel *ID) (*ID, error) return nil, nil } -func (r *persistentRegistry) Register(tunnel *ID) error { +func (r *persistentRegistry) Register(tunnel *ID) (rerr error) { glog.V(3).Infof("registering tunnel: %s", tunnel) if tunnel.Route == nil { return errors.New("tunnel.Route should not be nil") @@ -121,7 +124,7 @@ func (r *persistentRegistry) Register(tunnel *ID) error { defer func() { err := f.Close() if err != nil { - fmt.Errorf("error closing registry file: %s", err) + rerr = fmt.Errorf("error closing registry file: %s", err) } }() @@ -133,7 +136,7 @@ func (r *persistentRegistry) Register(tunnel *ID) error { return nil } -func (r *persistentRegistry) Remove(route *Route) error { +func (r *persistentRegistry) Remove(route *Route) (rerr error) { glog.V(3).Infof("removing tunnel from registry: %s", route) tunnels, err := r.List() if err != nil { @@ -158,7 +161,7 @@ func (r *persistentRegistry) Remove(route *Route) error { defer func() { err := f.Close() if err != nil { - fmt.Errorf("error closing tunnel registry file: %s", err) + rerr = fmt.Errorf("error closing tunnel registry file: %s", err) } }() diff --git a/pkg/minikube/tunnel/tunnel_manager.go b/pkg/minikube/tunnel/tunnel_manager.go index 285a9f0896ba..9a5868cc66c7 100644 --- a/pkg/minikube/tunnel/tunnel_manager.go +++ b/pkg/minikube/tunnel/tunnel_manager.go @@ -41,6 +41,7 @@ type Manager struct { //stateCheckInterval defines how frequently the cluster and route states are checked const stateCheckInterval = 5 * time.Second +// NewManager creates a new Manager func NewManager() *Manager { return &Manager{ delay: stateCheckInterval, @@ -50,6 +51,8 @@ func NewManager() *Manager { router: &osRouter{}, } } + +// StartTunnel starts the tunnel func (mgr *Manager) StartTunnel(ctx context.Context, machineName string, machineAPI libmachine.API, configLoader config.Loader, v1Core v1.CoreV1Interface) (done chan bool, err error) { tunnel, err := newTunnel(machineName, machineAPI, configLoader, v1Core, mgr.registry, mgr.router) if err != nil { @@ -117,6 +120,7 @@ func (mgr *Manager) cleanup(t controller) *Status { return t.cleanup() } +// CleanupNotRunningTunnels cleans up tunnels that are not running func (mgr *Manager) CleanupNotRunningTunnels() error { tunnels, err := mgr.registry.List() if err != nil { diff --git a/pkg/minikube/tunnel/types.go b/pkg/minikube/tunnel/types.go index a8540782e8f3..9a09b89148de 100644 --- a/pkg/minikube/tunnel/types.go +++ b/pkg/minikube/tunnel/types.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/types" ) +// Status represents the tunnel status type Status struct { TunnelID ID @@ -35,6 +36,7 @@ type Status struct { LoadBalancerEmulatorError error } +// Clone clones an existing Status func (t *Status) Clone() *Status { return &Status{ TunnelID: t.TunnelID, @@ -57,6 +59,7 @@ func (t *Status) String() string { t.LoadBalancerEmulatorError) } +// Route represents a route type Route struct { Gateway net.IP DestCIDR *net.IPNet @@ -66,12 +69,14 @@ func (r *Route) String() string { return fmt.Sprintf("%s -> %s", r.DestCIDR.String(), r.Gateway.String()) } +// Equal checks if two routes are equal func (r *Route) Equal(other *Route) bool { return other != nil && r.DestCIDR.IP.Equal(other.DestCIDR.IP) && r.DestCIDR.Mask.String() == other.DestCIDR.Mask.String() && r.Gateway.Equal(other.Gateway) } +// Patch represents a patch type Patch struct { Type types.PatchType NameSpace string @@ -82,12 +87,15 @@ type Patch struct { BodyContent string } -// State represents the status of a host +// HostState represents the status of a host type HostState int const ( + // Unknown represents an unknown state Unknown HostState = iota + // Running represents a running state Running + // Stopped represents a stopped state Stopped ) diff --git a/pkg/provision/buildroot.go b/pkg/provision/buildroot.go index a139114f93bc..50c701580da2 100644 --- a/pkg/provision/buildroot.go +++ b/pkg/provision/buildroot.go @@ -42,6 +42,7 @@ import ( "k8s.io/minikube/pkg/util" ) +// BuildrootProvisioner provisions the custom system based on Buildroot type BuildrootProvisioner struct { provision.SystemdProvisioner } @@ -52,6 +53,7 @@ func init() { }) } +// NewBuildrootProvisioner creates a new BuildrootProvisioner func NewBuildrootProvisioner(d drivers.Driver) provision.Provisioner { return &BuildrootProvisioner{ provision.NewSystemdProvisioner("buildroot", d), @@ -62,6 +64,7 @@ func (p *BuildrootProvisioner) String() string { return "buildroot" } +// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) { var engineCfg bytes.Buffer @@ -134,10 +137,12 @@ WantedBy=multi-user.target }, nil } +// Package installs a package func (p *BuildrootProvisioner) Package(name string, action pkgaction.PackageAction) error { return nil } +// Provision does the provisioning func (p *BuildrootProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error { p.SwarmOptions = swarmOptions p.AuthOptions = authOptions diff --git a/pkg/storage/storage_provisioner.go b/pkg/storage/storage_provisioner.go index e669377fa09b..abdda7e75926 100644 --- a/pkg/storage/storage_provisioner.go +++ b/pkg/storage/storage_provisioner.go @@ -44,6 +44,7 @@ type hostPathProvisioner struct { identity types.UID } +// NewHostPathProvisioner creates a new Provisioner using host paths func NewHostPathProvisioner() controller.Provisioner { return &hostPathProvisioner{ pvDir: "/tmp/hostpath-provisioner", @@ -99,7 +100,7 @@ func (p *hostPathProvisioner) Delete(volume *v1.PersistentVolume) error { return errors.New("identity annotation not found on PV") } if ann != string(p.identity) { - return &controller.IgnoredError{"identity annotation on PV does not match ours"} + return &controller.IgnoredError{Reason: "identity annotation on PV does not match ours"} } path := path.Join(p.pvDir, volume.Name) @@ -110,7 +111,7 @@ func (p *hostPathProvisioner) Delete(volume *v1.PersistentVolume) error { return nil } -// Start storage provisioner server +// StartStorageProvisioner will start storage provisioner server func StartStorageProvisioner() error { glog.Infof("Initializing the Minikube storage provisioner...") config, err := restclient.InClusterConfig() diff --git a/pkg/util/config.go b/pkg/util/config.go index fc62d9d4a45e..ea7fbeee7aa5 100644 --- a/pkg/util/config.go +++ b/pkg/util/config.go @@ -60,7 +60,7 @@ func setElement(e reflect.Value, v string) error { case net.IP: ip := net.ParseIP(v) if ip == nil { - return fmt.Errorf("Error converting input %s to an IP.", v) + return fmt.Errorf("Error converting input %s to an IP", v) } e.Set(reflect.ValueOf(ip)) case net.IPNet: @@ -99,7 +99,7 @@ func setElement(e reflect.Value, v string) error { case reflect.Bool: return convertBool(e, v) default: - return fmt.Errorf("Unable to set type %T.", e.Kind()) + return fmt.Errorf("Unable to set type %T", e.Kind()) } } diff --git a/pkg/util/constants.go b/pkg/util/constants.go index 9649b5877f0e..92f0c29bf5fb 100644 --- a/pkg/util/constants.go +++ b/pkg/util/constants.go @@ -70,6 +70,7 @@ func GetDNSIP(serviceCIDR string) (net.IP, error) { return ip, nil } +// GetAlternateDNS returns a list of alternate names for a domain func GetAlternateDNS(domain string) []string { return []string{"kubernetes.default.svc." + domain, "kubernetes.default.svc", "kubernetes.default", "kubernetes", "localhost"} } diff --git a/pkg/util/crypto.go b/pkg/util/crypto.go index 65263efc889e..dc8c552cd3e1 100644 --- a/pkg/util/crypto.go +++ b/pkg/util/crypto.go @@ -33,6 +33,7 @@ import ( "github.com/pkg/errors" ) +// GenerateCACert generates a CA certificate and RSA key for a common name func GenerateCACert(certPath, keyPath string, name string) error { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { @@ -60,6 +61,8 @@ func GenerateCACert(certPath, keyPath string, name string) error { // The certificate will be created with file mode 0644. The key will be created with file mode 0600. // If the certificate or key files already exist, they will be overwritten. // Any parent directories of the certPath or keyPath will be created as needed with file mode 0755. + +// GenerateSignedCert generates a signed certificate and key func GenerateSignedCert(certPath, keyPath, cn string, ips []net.IP, alternateDNS []string, signerCertPath, signerKeyPath string) error { signerCertBytes, err := ioutil.ReadFile(signerCertPath) if err != nil { @@ -67,7 +70,7 @@ func GenerateSignedCert(certPath, keyPath, cn string, ips []net.IP, alternateDNS } decodedSignerCert, _ := pem.Decode(signerCertBytes) if decodedSignerCert == nil { - return errors.New("Unable to decode certificate.") + return errors.New("Unable to decode certificate") } signerCert, err := x509.ParseCertificate(decodedSignerCert.Bytes) if err != nil { @@ -79,7 +82,7 @@ func GenerateSignedCert(certPath, keyPath, cn string, ips []net.IP, alternateDNS } decodedSignerKey, _ := pem.Decode(signerKeyBytes) if decodedSignerKey == nil { - return errors.New("Unable to decode key.") + return errors.New("Unable to decode key") } signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes) if err != nil { diff --git a/pkg/util/downloader.go b/pkg/util/downloader.go index d6f09e8eb04d..0571069d1d00 100644 --- a/pkg/util/downloader.go +++ b/pkg/util/downloader.go @@ -31,13 +31,16 @@ import ( const fileScheme = "file" +// ISODownloader downloads an ISO type ISODownloader interface { GetISOFileURI(isoURL string) string CacheMinikubeISOFromURL(isoURL string) error } +// DefaultDownloader is the default ISODownloader type DefaultDownloader struct{} +// GetISOFileURI gets the local destination for a remote source func (f DefaultDownloader) GetISOFileURI(isoURL string) string { urlObj, err := url.Parse(isoURL) if err != nil { @@ -51,6 +54,7 @@ func (f DefaultDownloader) GetISOFileURI(isoURL string) string { return "file://" + filepath.ToSlash(isoPath) } +// CacheMinikubeISOFromURL downloads the ISO, if it doesn't exist in cache func (f DefaultDownloader) CacheMinikubeISOFromURL(isoURL string) error { if !f.ShouldCacheMinikubeISO(isoURL) { glog.Infof("Not caching ISO, using %s", isoURL) @@ -67,8 +71,8 @@ func (f DefaultDownloader) CacheMinikubeISOFromURL(isoURL string) error { } // Validate the ISO if it was the default URL, before writing it to disk. - if isoURL == constants.DefaultIsoUrl { - options.Checksum = constants.DefaultIsoShaUrl + if isoURL == constants.DefaultISOURL { + options.Checksum = constants.DefaultISOSHAURL options.ChecksumHash = crypto.SHA256 } @@ -80,6 +84,7 @@ func (f DefaultDownloader) CacheMinikubeISOFromURL(isoURL string) error { return nil } +// ShouldCacheMinikubeISO returns if we need to download the ISO func (f DefaultDownloader) ShouldCacheMinikubeISO(isoURL string) bool { // store the minikube-iso inside the .minikube dir @@ -96,10 +101,12 @@ func (f DefaultDownloader) ShouldCacheMinikubeISO(isoURL string) bool { return true } +// GetISOCacheFilepath returns the path of an ISO in the local cache func (f DefaultDownloader) GetISOCacheFilepath(isoURL string) string { return filepath.Join(constants.GetMinipath(), "cache", "iso", filepath.Base(isoURL)) } +// IsMinikubeISOCached returns if an ISO exists in the local cache func (f DefaultDownloader) IsMinikubeISOCached(isoURL string) bool { if _, err := os.Stat(f.GetISOCacheFilepath(isoURL)); os.IsNotExist(err) { return false diff --git a/pkg/util/extra_options.go b/pkg/util/extra_options.go index 40554ae6f687..4409335d9099 100644 --- a/pkg/util/extra_options.go +++ b/pkg/util/extra_options.go @@ -21,6 +21,7 @@ import ( "strings" ) +// ExtraOption is an extra option type ExtraOption struct { Component string Key string @@ -31,8 +32,10 @@ func (e *ExtraOption) String() string { return fmt.Sprintf("%s.%s=%s", e.Component, e.Key, e.Value) } +// ExtraOptionSlice is a slice of ExtraOption type ExtraOptionSlice []ExtraOption +// Set parses the string value into a slice func (es *ExtraOptionSlice) Set(value string) error { // The component is the value before the first dot. componentSplit := strings.SplitN(value, ".", 2) @@ -56,6 +59,7 @@ func (es *ExtraOptionSlice) Set(value string) error { return nil } +// String converts the slice to a string value func (es *ExtraOptionSlice) String() string { s := []string{} for _, e := range *es { @@ -64,6 +68,7 @@ func (es *ExtraOptionSlice) String() string { return strings.Join(s, " ") } +// Type returns the type func (es *ExtraOptionSlice) Type() string { return "ExtraOption" } diff --git a/pkg/util/kubeconfig/config.go b/pkg/util/kubeconfig.go similarity index 96% rename from pkg/util/kubeconfig/config.go rename to pkg/util/kubeconfig.go index f75a317d8717..3545576b6579 100644 --- a/pkg/util/kubeconfig/config.go +++ b/pkg/util/kubeconfig.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubeconfig +package util import ( "fmt" @@ -31,9 +31,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/tools/clientcmd/api/latest" - "k8s.io/minikube/pkg/util" ) +// KubeConfigSetup is the kubeconfig setup type KubeConfigSetup struct { // The name of the cluster for this context ClusterName string @@ -61,10 +61,12 @@ type KubeConfigSetup struct { kubeConfigFile atomic.Value } +// SetKubeConfigFile sets the kubeconfig file func (k *KubeConfigSetup) SetKubeConfigFile(kubeConfigFile string) { k.kubeConfigFile.Store(kubeConfigFile) } +// GetKubeConfigFile gets the kubeconfig file func (k *KubeConfigSetup) GetKubeConfigFile() string { return k.kubeConfigFile.Load().(string) } @@ -197,7 +199,7 @@ func WriteConfig(config *api.Config, filename string) error { if err := ioutil.WriteFile(filename, data, 0600); err != nil { return errors.Wrapf(err, "Error writing file %s", filename) } - if err := util.MaybeChownDirRecursiveToMinikubeUser(dir); err != nil { + if err := MaybeChownDirRecursiveToMinikubeUser(dir); err != nil { return errors.Wrapf(err, "Error recursively changing ownership for dir: %s", dir) } @@ -301,11 +303,11 @@ func getPortFromKubeConfig(filename, machineName string) (int, error) { } kurl, err := url.Parse(cluster.Server) if err != nil { - return util.APIServerPort, nil + return APIServerPort, nil } _, kport, err := net.SplitHostPort(kurl.Host) if err != nil { - return util.APIServerPort, nil + return APIServerPort, nil } port, err := strconv.Atoi(kport) return port, err diff --git a/pkg/util/kubeconfig/config_test.go b/pkg/util/kubeconfig_test.go similarity index 98% rename from pkg/util/kubeconfig/config_test.go rename to pkg/util/kubeconfig_test.go index f68ef8e2170c..b479244e008d 100644 --- a/pkg/util/kubeconfig/config_test.go +++ b/pkg/util/kubeconfig_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubeconfig +package util import ( "io/ioutil" @@ -25,7 +25,6 @@ import ( "testing" "k8s.io/client-go/tools/clientcmd/api" - "k8s.io/minikube/pkg/util" ) var fakeKubeCfg = []byte(` @@ -395,7 +394,7 @@ func minikubeConfig(config *api.Config) { // cluster clusterName := "minikube" cluster := api.NewCluster() - cluster.Server = "https://192.168.99.100:" + strconv.Itoa(util.APIServerPort) + cluster.Server = "https://192.168.99.100:" + strconv.Itoa(APIServerPort) cluster.CertificateAuthority = "/home/tux/.minikube/apiserver.crt" config.Clusters[clusterName] = cluster diff --git a/pkg/util/kubernetes.go b/pkg/util/kubernetes.go index 5c07aa68bca9..debe31b98cba 100644 --- a/pkg/util/kubernetes.go +++ b/pkg/util/kubernetes.go @@ -45,12 +45,14 @@ var ( ReasonableStartTime = time.Minute * 10 ) +// PodStore stores pods type PodStore struct { cache.Store stopCh chan struct{} Reflector *cache.Reflector } +// List lists the pods func (s *PodStore) List() []*v1.Pod { objects := s.Store.List() pods := make([]*v1.Pod, 0) @@ -60,10 +62,12 @@ func (s *PodStore) List() []*v1.Pod { return pods } +// Stop stops the pods func (s *PodStore) Stop() { close(s.stopCh) } +// GetClient gets the client from config func GetClient() (kubernetes.Interface, error) { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() configOverrides := &clientcmd.ConfigOverrides{} @@ -79,6 +83,7 @@ func GetClient() (kubernetes.Interface, error) { return client, nil } +// NewPodStore creates a new PodStore func NewPodStore(c kubernetes.Interface, namespace string, label labels.Selector, field fields.Selector) *PodStore { lw := &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { @@ -100,6 +105,7 @@ func NewPodStore(c kubernetes.Interface, namespace string, label labels.Selector return &PodStore{Store: store, stopCh: stopCh, Reflector: reflector} } +// StartPods starts all pods func StartPods(c kubernetes.Interface, namespace string, pod v1.Pod, waitForRunning bool) error { pod.ObjectMeta.Labels["name"] = pod.Name if waitForRunning { @@ -285,6 +291,7 @@ func countEndpointsNum(e *v1.Endpoints) int { return num } +// IsRetryableAPIError returns if this error is retryable or not func IsRetryableAPIError(err error) bool { return apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) || apierrs.IsTooManyRequests(err) || apierrs.IsInternalError(err) } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 10fbc62fb01c..7637e2a588b3 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -35,19 +35,24 @@ import ( "github.com/pkg/errors" ) +// ErrPrefix notes an error const ErrPrefix = "! " + +// OutPrefix notes output const OutPrefix = "> " const ( downloadURL = "https://storage.googleapis.com/minikube/releases/%s/minikube-%s-amd64%s" ) +// RetriableError is an error that can be tried again type RetriableError struct { Err error } func (r RetriableError) Error() string { return "Temporary Error: " + r.Err.Error() } +// CalculateDiskSizeInMB returns the number of MB in the human readable string func CalculateDiskSizeInMB(humanReadableDiskSize string) int { diskSize, err := units.FromHumanSize(humanReadableDiskSize) if err != nil { @@ -78,12 +83,13 @@ func Until(fn func() error, w io.Writer, name string, sleep time.Duration, done } } +// Pad pads the string with newlines func Pad(str string) string { return fmt.Sprintf("\n%s\n", str) } -// If the file represented by path exists and -// readable, return true otherwise return false. +// CanReadFile returns true if the file represented +// by path exists and is readable, otherwise false. func CanReadFile(path string) bool { f, err := os.Open(path) if err != nil { @@ -95,10 +101,12 @@ func CanReadFile(path string) bool { return true } +// Retry retries a number of attempts func Retry(attempts int, callback func() error) (err error) { return RetryAfter(attempts, callback, 0) } +// RetryAfter retries a number of attempts, after a delay func RetryAfter(attempts int, callback func() error, d time.Duration) (err error) { m := MultiError{} for i := 0; i < attempts; i++ { @@ -120,6 +128,7 @@ func RetryAfter(attempts int, callback func() error, d time.Duration) (err error return m.ToError() } +// ParseSHAFromURL downloads and reads a SHA checksum from an URL func ParseSHAFromURL(url string) (string, error) { r, err := http.Get(url) if err != nil { @@ -137,6 +146,7 @@ func ParseSHAFromURL(url string) (string, error) { return strings.Trim(string(body), "\n"), nil } +// GetBinaryDownloadURL returns a suitable URL for the platform func GetBinaryDownloadURL(version, platform string) string { switch platform { case "windows": @@ -146,16 +156,19 @@ func GetBinaryDownloadURL(version, platform string) string { } } +// MultiError holds multiple errors type MultiError struct { Errors []error } +// Collect adds the error func (m *MultiError) Collect(err error) { if err != nil { m.Errors = append(m.Errors, err) } } +// ToError converts all errors into one func (m MultiError) ToError() error { if len(m.Errors) == 0 { return nil @@ -168,6 +181,7 @@ func (m MultiError) ToError() error { return errors.New(strings.Join(errStrings, "\n")) } +// IsDirectory checks if path is a directory func IsDirectory(path string) (bool, error) { fileInfo, err := os.Stat(path) if err != nil { @@ -176,6 +190,7 @@ func IsDirectory(path string) (bool, error) { return fileInfo.IsDir(), nil } +// ChownR does a recursive os.Chown func ChownR(path string, uid, gid int) error { return filepath.Walk(path, func(name string, info os.FileInfo, err error) error { if err == nil { @@ -185,6 +200,7 @@ func ChownR(path string, uid, gid int) error { }) } +// MaybeChownDirRecursiveToMinikubeUser changes ownership of a dir, if requested func MaybeChownDirRecursiveToMinikubeUser(dir string) error { if os.Getenv("CHANGE_MINIKUBE_NONE_USER") != "" && os.Getenv("SUDO_USER") != "" { username := os.Getenv("SUDO_USER") diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index f1027a7e4c96..f7d1c7c372fe 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -34,13 +34,12 @@ func errorGenerator(n int, retryable bool) func() error { errorCount := 0 return func() (err error) { if errorCount < n { - errorCount += 1 - e := errors.New("Error!") + errorCount++ + e := errors.New("Error") if retryable { return &RetriableError{Err: e} - } else { - return e } + return e } diff --git a/pkg/version/version.go b/pkg/version/version.go index c64e8e33df8a..116d08b54a7f 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -22,28 +22,35 @@ import ( "github.com/blang/semver" ) -// The current version of the minikube -// This is a private field and should be set when compiling with --ldflags="-X k8s.io/minikube/pkg/version.version=vX.Y.Z" +// VersionPrefix is the prefix of the git tag for a version const VersionPrefix = "v" +// The current version of the minikube + +// version is a private field and should be set when compiling with --ldflags="-X k8s.io/minikube/pkg/version.version=vX.Y.Z" var version = "v0.0.0-unset" +// isoVersion is a private field and should be set when compiling with --ldflags="-X k8s.io/minikube/pkg/version.isoVersion=vX.Y.Z" var isoVersion = "v0.0.0-unset" var isoPath = "minikube/iso" +// GetVersion returns the current minikube version func GetVersion() string { return version } -func GetIsoVersion() string { +// GetISOVersion returns the current minikube.iso version +func GetISOVersion() string { return isoVersion } -func GetIsoPath() string { +// GetISOPath returns the remote path to the minikube.iso +func GetISOPath() string { return isoPath } +// GetSemverVersion returns the current minikube semantic version (semver) func GetSemverVersion() (semver.Version, error) { return semver.Make(strings.TrimPrefix(GetVersion(), VersionPrefix)) } diff --git a/test/integration/flags.go b/test/integration/flags.go index 06d0911871d4..5a5746ac7d06 100644 --- a/test/integration/flags.go +++ b/test/integration/flags.go @@ -24,6 +24,7 @@ import ( "k8s.io/minikube/test/integration/util" ) +// TestMain is the test main func TestMain(m *testing.M) { flag.Parse() os.Exit(m.Run()) @@ -35,6 +36,7 @@ var startArgs = flag.String("minikube-start-args", "", "Arguments to pass to min var mountArgs = flag.String("minikube-mount-args", "", "Arguments to pass to minikube mount") var testdataDir = flag.String("testdata-dir", "testdata", "the directory relative to test/integration where the testdata lives") +// NewMinikubeRunner creates a new MinikubeRunner func NewMinikubeRunner(t *testing.T) util.MinikubeRunner { return util.MinikubeRunner{ Args: *args, diff --git a/test/integration/util/util.go b/test/integration/util/util.go index 51e8f15468fc..83cbc67f8b8d 100644 --- a/test/integration/util/util.go +++ b/test/integration/util/util.go @@ -39,6 +39,7 @@ import ( const kubectlBinary = "kubectl" +// MinikubeRunner runs a command type MinikubeRunner struct { T *testing.T BinaryPath string @@ -57,11 +58,13 @@ func Logf(str string, args ...interface{}) { fmt.Println(fmt.Sprintf(str, args...)) } +// Run executes a command func (m *MinikubeRunner) Run(cmd string) error { _, err := m.SSH(cmd) return err } +// Copy copies a file func (m *MinikubeRunner) Copy(f assets.CopyableFile) error { path, _ := filepath.Abs(m.BinaryPath) cmd := exec.Command("/bin/bash", "-c", path, "ssh", "--", fmt.Sprintf("cat >> %s", filepath.Join(f.GetTargetDir(), f.GetTargetName()))) @@ -69,10 +72,12 @@ func (m *MinikubeRunner) Copy(f assets.CopyableFile) error { return cmd.Run() } +// CombinedOutput executes a command, returning the combined stdout and stderr func (m *MinikubeRunner) CombinedOutput(cmd string) (string, error) { return m.SSH(cmd) } +// Remove removes a file func (m *MinikubeRunner) Remove(f assets.CopyableFile) error { _, err := m.SSH(fmt.Sprintf("rm -rf %s", filepath.Join(f.GetTargetDir(), f.GetTargetName()))) return err @@ -111,6 +116,7 @@ func (m *MinikubeRunner) teeRun(cmd *exec.Cmd) (string, string, error) { return outB.String(), errB.String(), err } +// RunCommand executes a command, optionally checking for error func (m *MinikubeRunner) RunCommand(command string, checkError bool) string { commandArr := strings.Split(command, " ") path, _ := filepath.Abs(m.BinaryPath) @@ -136,6 +142,7 @@ func (m *MinikubeRunner) RunWithContext(ctx context.Context, command string) (st return m.teeRun(cmd) } +// RunDaemon executes a command, returning the stdout func (m *MinikubeRunner) RunDaemon(command string) (*exec.Cmd, *bufio.Reader) { commandArr := strings.Split(command, " ") path, _ := filepath.Abs(m.BinaryPath) @@ -164,6 +171,7 @@ func (m *MinikubeRunner) RunDaemon(command string) (*exec.Cmd, *bufio.Reader) { } +// RunDaemon2 executes a command, returning the stdout and stderr func (m *MinikubeRunner) RunDaemon2(command string) (*exec.Cmd, *bufio.Reader, *bufio.Reader) { commandArr := strings.Split(command, " ") path, _ := filepath.Abs(m.BinaryPath) @@ -183,7 +191,7 @@ func (m *MinikubeRunner) RunDaemon2(command string) (*exec.Cmd, *bufio.Reader, * } return cmd, bufio.NewReader(stdoutPipe), bufio.NewReader(stderrPipe) } - +// SSH returns the output of running a command using SSH func (m *MinikubeRunner) SSH(command string) (string, error) { path, _ := filepath.Abs(m.BinaryPath) cmd := exec.Command(path, "ssh", command) @@ -197,11 +205,13 @@ func (m *MinikubeRunner) SSH(command string) (string, error) { return string(stdout), nil } +// Start starts the container runtime func (m *MinikubeRunner) Start(opts ...string) { cmd := fmt.Sprintf("start %s %s %s --alsologtostderr --v=2", m.StartArgs, m.Args, strings.Join(opts, " ")) m.RunCommand(cmd, true) } +// EnsureRunning makes sure the container runtime is running func (m *MinikubeRunner) EnsureRunning() { if m.GetStatus() != "Running" { m.Start() @@ -219,20 +229,24 @@ func (m *MinikubeRunner) ParseEnvCmdOutput(out string) map[string]string { return env } +// GetStatus returns the status of a service func (m *MinikubeRunner) GetStatus() string { return m.RunCommand(fmt.Sprintf("status --format={{.Host}} %s", m.Args), false) } +// GetLogs returns the logs of a service func (m *MinikubeRunner) GetLogs() string { return m.RunCommand(fmt.Sprintf("logs %s", m.Args), true) } +// CheckStatus makes sure the service has the desired status, or cause fatal error func (m *MinikubeRunner) CheckStatus(desired string) { if err := m.CheckStatusNoFail(desired); err != nil { m.T.Fatalf("%v", err) } } +// CheckStatusNoFail makes sure the service has the desired status, returning error func (m *MinikubeRunner) CheckStatusNoFail(desired string) error { s := m.GetStatus() if s != desired { @@ -241,11 +255,13 @@ func (m *MinikubeRunner) CheckStatusNoFail(desired string) error { return nil } +// KubectlRunner runs a command using kubectl type KubectlRunner struct { T *testing.T BinaryPath string } +// NewKubectlRunner creates a new KubectlRunner func NewKubectlRunner(t *testing.T) *KubectlRunner { p, err := exec.LookPath(kubectlBinary) if err != nil { @@ -254,6 +270,7 @@ func NewKubectlRunner(t *testing.T) *KubectlRunner { return &KubectlRunner{BinaryPath: p, T: t} } +// RunCommandParseOutput runs a command and parses the JSON output func (k *KubectlRunner) RunCommandParseOutput(args []string, outputObj interface{}) error { args = append(args, "-o=json") output, err := k.RunCommand(args) @@ -267,6 +284,7 @@ func (k *KubectlRunner) RunCommandParseOutput(args []string, outputObj interface return nil } +// RunCommand runs a command, returning stdout func (k *KubectlRunner) RunCommand(args []string) (stdout []byte, err error) { inner := func() error { cmd := exec.Command(k.BinaryPath, args...) @@ -283,6 +301,7 @@ func (k *KubectlRunner) RunCommand(args []string) (stdout []byte, err error) { return stdout, err } +// CreateRandomNamespace creates a random namespace func (k *KubectlRunner) CreateRandomNamespace() string { const strLen = 20 name := genRandString(strLen) @@ -302,11 +321,13 @@ func genRandString(strLen int) string { return string(result) } +// DeleteNamespace deletes the namespace func (k *KubectlRunner) DeleteNamespace(namespace string) error { _, err := k.RunCommand([]string{"delete", "namespace", namespace}) return err } +// WaitForBusyboxRunning waits until busybox pod to be running func WaitForBusyboxRunning(t *testing.T, namespace string) error { client, err := commonutil.GetClient() if err != nil { @@ -316,6 +337,7 @@ func WaitForBusyboxRunning(t *testing.T, namespace string) error { return commonutil.WaitForPodsWithLabelRunning(client, namespace, selector) } +// WaitForIngressControllerRunning waits until ingress controller pod to be running func WaitForIngressControllerRunning(t *testing.T) error { client, err := commonutil.GetClient() if err != nil { @@ -334,6 +356,7 @@ func WaitForIngressControllerRunning(t *testing.T) error { return nil } +// WaitForIngressDefaultBackendRunning waits until ingress default backend pod to be running func WaitForIngressDefaultBackendRunning(t *testing.T) error { client, err := commonutil.GetClient() if err != nil { @@ -409,6 +432,7 @@ func WaitForFailedCreatePodSandBoxEvent() error { return nil } +// WaitForNginxRunning waits for nginx service to be up func WaitForNginxRunning(t *testing.T) error { client, err := commonutil.GetClient() @@ -427,6 +451,7 @@ func WaitForNginxRunning(t *testing.T) error { return nil } +// Retry tries the callback for a number of attempts, with a delay between attempts func Retry(t *testing.T, callback func() error, d time.Duration, attempts int) (err error) { for i := 0; i < attempts; i++ { err = callback() diff --git a/third_party/go9p/srv_conn.go b/third_party/go9p/srv_conn.go index 4f9e1bdc72e3..d043d279807d 100644 --- a/third_party/go9p/srv_conn.go +++ b/third_party/go9p/srv_conn.go @@ -210,8 +210,6 @@ func (conn *Conn) send() { } } } - - panic("unreached") } func (conn *Conn) RemoteAddr() net.Addr { @@ -259,5 +257,4 @@ func (srv *Srv) StartListener(l net.Listener) error { srv.NewConn(c) } - return nil } diff --git a/third_party/go9p/ufs_linux.go b/third_party/go9p/ufs_linux.go index c2fd46ef8c64..23d3d9e42490 100644 --- a/third_party/go9p/ufs_linux.go +++ b/third_party/go9p/ufs_linux.go @@ -19,14 +19,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 { @@ -42,11 +40,11 @@ func dir2Qid(d os.FileInfo) *Qid { func dir2Dir(path string, d os.FileInfo, dotu bool, upool Users) (*Dir, error) { if r := recover(); r != nil { fmt.Print("stat failed: ", r) - return nil, &os.PathError{"dir2Dir", path, nil} + return nil, &os.PathError{Op: "dir2Dir", Path: path, Err: nil} } sysif := d.Sys() if sysif == nil { - return nil, &os.PathError{"dir2Dir: sysif is nil", path, nil} + return nil, &os.PathError{Op: "dir2Dir: sysif is nil", Path: path, Err: nil} } sysMode := sysif.(*syscall.Stat_t)