diff --git a/cli/cluster/cluster.go b/cli/cluster/cluster.go index ad9bdf8ef3..590462113b 100644 --- a/cli/cluster/cluster.go +++ b/cli/cluster/cluster.go @@ -17,7 +17,6 @@ import ( "encoding/json" "fmt" "log" - "strings" "time" "github.com/docker/machine/drivers/virtualbox" @@ -42,15 +41,12 @@ func StartHost(api libmachine.API) (*host.Host, error) { } } -// StartCluster starts as k8s cluster on the specified Host. -func StartCluster(h *host.Host) (string, error) { - host, err := h.Driver.GetURL() - if err != nil { - return "", err - } - kubeHost := strings.Replace(host, "tcp://", "http://", -1) - kubeHost = strings.Replace(kubeHost, ":2376", ":8080", -1) +type sshAble interface { + RunSSHCommand(string) (string, error) +} +// StartCluster starts as k8s cluster on the specified Host. +func StartCluster(h sshAble) error { for _, cmd := range []string{ // Download and install weave, if it doesn't exist. `if [ ! -e /usr/local/bin/weave ]; @@ -75,11 +71,11 @@ func StartCluster(h *host.Host) (string, error) { output, err := h.RunSSHCommand(cmd) log.Println(output) if err != nil { - return "", err + return err } } - return kubeHost, nil + return nil } func createHost(api libmachine.API) (*host.Host, error) { diff --git a/cli/cluster/cluster_test.go b/cli/cluster/cluster_test.go index df5debd76e..690a5f1d94 100644 --- a/cli/cluster/cluster_test.go +++ b/cli/cluster/cluster_test.go @@ -1,8 +1,10 @@ package cluster import ( + "fmt" "testing" + "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/state" "github.com/kubernetes/minikube/cli/constants" "github.com/kubernetes/minikube/cli/tests" @@ -37,3 +39,73 @@ func TestCreateHost(t *testing.T) { t.Fatalf("Wrong driver name: %v. Should be virtualbox.", h.DriverName) } } + +type mockHost struct { + Commands []string +} + +func (m mockHost) RunSSHCommand(cmd string) (string, error) { + m.Commands = append(m.Commands, cmd) + return "", nil +} + +func TestStartCluster(t *testing.T) { + h := mockHost{} + err := StartCluster(h) + if err != nil { + t.Fatalf("Error starting cluster: %s", err) + } +} + +type mockHostError struct{} + +func (m mockHostError) RunSSHCommand(cmd string) (string, error) { + return "", fmt.Errorf("Error calling command: %s", cmd) +} + +func TestStartClusterError(t *testing.T) { + h := mockHostError{} + err := StartCluster(h) + if err == nil { + t.Fatal("Error not thrown starting cluster.") + } +} + +func TestStartHostExists(t *testing.T) { + api := &tests.MockAPI{} + // Create an initial host. + _, err := createHost(api) + if err != nil { + t.Fatalf("Error creating host: %v", err) + } + + // Make sure the next call to Create will fail, to assert it doesn't get called again. + api.CreateError = true + if err := api.Create(&host.Host{}); err == nil { + t.Fatal("api.Create did not fail, but should have.") + } + + // This should pass without calling Create because the host exists already. + h, err := StartHost(api) + if err != nil { + t.Fatal("Error starting host.") + } + if h.Name != constants.MachineName { + t.Fatalf("Machine created with incorrect name: %s", h.Name) + } +} + +func TestStartHost(t *testing.T) { + api := &tests.MockAPI{} + + h, err := StartHost(api) + if err != nil { + t.Fatal("Error starting host.") + } + if h.Name != constants.MachineName { + t.Fatalf("Machine created with incorrect name: %s", h.Name) + } + if exists, _ := api.Exists(h.Name); !exists { + t.Fatal("Machine not saved.") + } +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go index cf480ebece..74845cdb42 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -39,6 +39,14 @@ clusters optimized for development workflows. `, PersistentPreRun: func(cmd *cobra.Command, args []string) { localbinary.CurrentBinaryIsDockerMachine = true + + for _, path := range dirs { + if err := os.MkdirAll(path, 0777); err != nil { + log.Panicf("Error creating minikube directory: %s", err) + } + } + }, + Run: func(cmd *cobra.Command, args []string) { if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal { driverName := os.Getenv(localbinary.PluginEnvDriverName) switch driverName { @@ -50,12 +58,6 @@ clusters optimized for development workflows. } return } - - for _, path := range dirs { - if err := os.MkdirAll(path, 0777); err != nil { - log.Panicf("Error creating minikube directory: %s", err) - } - } }, } diff --git a/cli/cmd/root_test.go b/cli/cmd/root_test.go index 36e901b097..dfb06761ff 100644 --- a/cli/cmd/root_test.go +++ b/cli/cmd/root_test.go @@ -22,10 +22,10 @@ func makeTempDir() string { return tempDir } -func runCommand() { +func runCommand(f func(*cobra.Command, []string)) { cmd := cobra.Command{} var args []string - RootCmd.PersistentPreRun(&cmd, args) + f(&cmd, args) } func TestPreRunDirectories(t *testing.T) { @@ -33,7 +33,7 @@ func TestPreRunDirectories(t *testing.T) { tempDir := makeTempDir() defer os.RemoveAll(tempDir) - runCommand() + runCommand(RootCmd.PersistentPreRun) for _, dir := range dirs { _, err := os.Stat(dir) @@ -46,13 +46,13 @@ func TestPreRunDirectories(t *testing.T) { func TestPreRunNotDriver(t *testing.T) { tempDir := makeTempDir() defer os.RemoveAll(tempDir) - runCommand() + runCommand(RootCmd.PersistentPreRun) if !localbinary.CurrentBinaryIsDockerMachine { t.Fatal("CurrentBinaryIsDockerMachine not set. This will break driver initialization.") } } -func TestPreRunDriver(t *testing.T) { +func TestRunDriver(t *testing.T) { // This test is a bit complicated. It verifies that when the root command is // called with the proper environment variables, we setup the libmachine driver. @@ -70,7 +70,7 @@ func TestPreRunDriver(t *testing.T) { }() // Run the command asynchronously. It should listen on a port for connections. - go runCommand() + go runCommand(RootCmd.Run) // The command will write out what port it's listening on over stdout. reader := bufio.NewReader(r) diff --git a/cli/cmd/start.go b/cli/cmd/start.go index 92e3ae11ad..283886d300 100644 --- a/cli/cmd/start.go +++ b/cli/cmd/start.go @@ -17,6 +17,7 @@ import ( "fmt" "log" "os" + "strings" "github.com/docker/machine/libmachine" "github.com/kubernetes/minikube/cli/cluster" @@ -43,11 +44,18 @@ func runStart(cmd *cobra.Command, args []string) { log.Println("Error starting host: ", err) os.Exit(1) } - kubeHost, err := cluster.StartCluster(host) - if err != nil { + + if err := cluster.StartCluster(host); err != nil { log.Println("Error starting cluster: ", err) os.Exit(1) } + + kubeHost, err := host.Driver.GetURL() + if err != nil { + log.Println("Error connecting to cluster: ", err) + } + kubeHost = strings.Replace(kubeHost, "tcp://", "http://", -1) + kubeHost = strings.Replace(kubeHost, ":2376", ":8080", -1) log.Printf("Kubernetes is available at %s.\n", kubeHost) log.Println("Run this command to use the cluster: ") log.Printf("kubectl config set-cluster minikube --insecure-skip-tls-verify=true --server=%s\n", kubeHost) diff --git a/cli/constants/constants.go b/cli/constants/constants.go index aebb313ea5..a959aa5bab 100644 --- a/cli/constants/constants.go +++ b/cli/constants/constants.go @@ -5,11 +5,13 @@ import ( "path/filepath" ) +// MachineName is the name to use for the VM. const MachineName = "minikubeVM" // Fix for windows -var Minipath = filepath.Join(os.Getenv("HOME"), "minikube") +var Minipath = filepath.Join(os.Getenv("HOME"), ".minikube") +// MakeMiniPath is a utility to calculate a relative path to our directory. func MakeMiniPath(fileName string) string { return filepath.Join(Minipath, fileName) } diff --git a/cli/tests/api_mock.go b/cli/tests/api_mock.go index 14a78b89d5..0f35f57161 100644 --- a/cli/tests/api_mock.go +++ b/cli/tests/api_mock.go @@ -2,6 +2,7 @@ package tests import ( "encoding/json" + "fmt" "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/auth" @@ -10,6 +11,12 @@ import ( "github.com/docker/machine/libmachine/state" ) +// MockAPI is a struct used to mock out libmachine.API +type MockAPI struct { + Hosts []*host.Host + CreateError bool +} + // Close closes the API. func (api *MockAPI) Close() error { return nil @@ -33,6 +40,9 @@ func (api *MockAPI) NewHost(driverName string, rawDriver []byte) (*host.Host, er // Create creates the actual host. func (api *MockAPI) Create(h *host.Host) error { + if api.CreateError { + return fmt.Errorf("Error creating host.") + } return h.Driver.Create() } diff --git a/cli/tests/driver_mock.go b/cli/tests/driver_mock.go index da79026c21..f7e904b4a9 100644 --- a/cli/tests/driver_mock.go +++ b/cli/tests/driver_mock.go @@ -2,16 +2,10 @@ package tests import ( "github.com/docker/machine/libmachine/drivers" - "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/mcnflag" "github.com/docker/machine/libmachine/state" ) -// MockAPI is a struct used to mock out libmachine.API -type MockAPI struct { - Hosts []*host.Host -} - // MockDriver is a struct used to mock out libmachine.Driver type MockDriver struct { drivers.BaseDriver