Add delete command and tests. (#26)

* Add stop command and tests.

Fix bug in start command where stopped hosts weren't started.

* Add delete command and tests.
pull/27/head
dlorenc 2016-04-26 12:58:28 -07:00
parent 969b6b0d7c
commit 609aeeea92
6 changed files with 174 additions and 19 deletions

View File

@ -17,6 +17,7 @@ import (
"encoding/json"
"fmt"
"log"
"strings"
"time"
"github.com/docker/machine/drivers/virtualbox"
@ -63,6 +64,40 @@ func StopHost(api libmachine.API) error {
return nil
}
type multiError struct {
Errors []error
}
func (m *multiError) Collect(err error) {
if err != nil {
m.Errors = append(m.Errors, err)
}
}
func (m multiError) ToError() error {
if len(m.Errors) == 0 {
return nil
}
errStrings := []string{}
for _, err := range m.Errors {
errStrings = append(errStrings, err.Error())
}
return fmt.Errorf(strings.Join(errStrings, "\n"))
}
// DeleteHost deletes the host VM.
func DeleteHost(api libmachine.API) error {
host, err := api.Load(constants.MachineName)
if err != nil {
return err
}
m := multiError{}
m.Collect(host.Driver.Remove())
m.Collect(api.Remove(constants.MachineName))
return m.ToError()
}
type sshAble interface {
RunSSHCommand(string) (string, error)
}

View File

@ -2,6 +2,7 @@ package cluster
import (
"fmt"
"strings"
"testing"
"github.com/docker/machine/libmachine/host"
@ -156,4 +157,79 @@ func TestStopHost(t *testing.T) {
if s, _ := h.Driver.GetState(); s != state.Stopped {
t.Fatalf("Machine not stopped. Currently in state: %s", s)
}
}
func TestMultiError(t *testing.T) {
m := multiError{}
m.Collect(fmt.Errorf("Error 1"))
m.Collect(fmt.Errorf("Error 2"))
err := m.ToError()
expected := `Error 1
Error 2`
if err.Error() != expected {
t.Fatalf("%s != %s", err, expected)
}
m = multiError{}
if err := m.ToError(); err != nil {
t.Fatalf("Unexpected error: %s", err)
}
}
func TestDeleteHost(t *testing.T) {
api := &tests.MockAPI{}
createHost(api)
if err := DeleteHost(api); err != nil {
t.Fatalf("Unexpected error deleting host: %s", err)
}
}
func TestDeleteHostErrorDeletingVM(t *testing.T) {
api := &tests.MockAPI{}
h, _ := createHost(api)
d := &tests.MockDriver{RemoveError: true}
h.Driver = d
if err := DeleteHost(api); err == nil {
t.Fatal("Expected error deleting host.")
}
}
func TestDeleteHostErrorDeletingFiles(t *testing.T) {
api := &tests.MockAPI{RemoveError: true}
createHost(api)
if err := DeleteHost(api); err == nil {
t.Fatal("Expected error deleting host.")
}
}
func TestDeleteHostMultipleErrors(t *testing.T) {
api := &tests.MockAPI{
RemoveError: true,
}
h, _ := createHost(api)
d := &tests.MockDriver{RemoveError: true}
h.Driver = d
err := DeleteHost(api)
if err == nil {
t.Fatal("Expected error deleting host, didn't get one.")
}
expectedErrors := []string{"Error removing minikubeVM", "Error deleting machine"}
for _, expectedError := range expectedErrors {
if !strings.Contains(err.Error(), expectedError) {
t.Fatalf("Error %s expected to contain: %s. ", err)
}
}
}

48
cli/cmd/delete.go Normal file
View File

@ -0,0 +1,48 @@
// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import (
"fmt"
"os"
"github.com/docker/machine/libmachine"
"github.com/kubernetes/minikube/cli/cluster"
"github.com/kubernetes/minikube/cli/constants"
"github.com/spf13/cobra"
)
// deleteCmd represents the delete command
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "Deletes a local kubernetes cluster.",
Long: `Deletes a local kubernetes cluster. This command deletes the VM, and removes all
associated files.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Deleting local Kubernetes cluster...")
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
defer api.Close()
if err := cluster.DeleteHost(api); err != nil {
fmt.Println("Errors occurred deleting machine: ", err)
os.Exit(1)
}
fmt.Println("Machine deleted.")
},
}
func init() {
RootCmd.AddCommand(deleteCmd)
}

View File

@ -26,20 +26,16 @@ import (
// stopCmd represents the stop command
var stopCmd = &cobra.Command{
Use: "stop",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Short: "Stops a running local kubernetes cluster.",
Long: `Stops a local kubernetes cluster running in Virtualbox. This command stops the VM
itself, leaving all files intact. The cluster can be started again with the "start" command.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Stopping local Kubernetes cluster...")
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
defer api.Close()
if err := cluster.StopHost(api); err != nil {
fmt.Println("Error stopping machine: %s", err)
fmt.Println("Error stopping machine: ", err)
os.Exit(1)
}
fmt.Println("Machine stopped.")
@ -48,15 +44,4 @@ to quickly create a Cobra application.`,
func init() {
RootCmd.AddCommand(stopCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// stopCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// stopCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

View File

@ -15,6 +15,7 @@ import (
type MockAPI struct {
Hosts []*host.Host
CreateError bool
RemoveError bool
}
// Close closes the API.
@ -77,6 +78,10 @@ func (api *MockAPI) Load(name string) (*host.Host, error) {
// Remove a host.
func (api *MockAPI) Remove(name string) error {
if api.RemoveError {
return fmt.Errorf("Error removing %s", name)
}
newHosts := []*host.Host{}
for _, host := range api.Hosts {

View File

@ -1,6 +1,8 @@
package tests
import (
"fmt"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/state"
@ -10,6 +12,7 @@ import (
type MockDriver struct {
drivers.BaseDriver
CurrentState state.State
RemoveError bool
}
// Create creates a MockDriver instance
@ -46,6 +49,9 @@ func (driver *MockDriver) Kill() error {
// Remove removes the machine
func (driver *MockDriver) Remove() error {
if driver.RemoveError {
return fmt.Errorf("Error deleting machine.")
}
return nil
}