FIX #2086 Add an error column to ls

Signed-off-by: David Gageot <david@gageot.net>
This commit is contained in:
David Gageot 2015-11-23 10:53:47 +01:00
parent f9979c285d
commit 9039cbba3d
3 changed files with 53 additions and 75 deletions

View File

@ -39,6 +39,7 @@ type HostListItem struct {
State state.State
URL string
SwarmOptions *swarm.Options
Error string
}
func cmdLs(c CommandLine, api libmachine.API) error {
@ -67,7 +68,7 @@ func cmdLs(c CommandLine, api libmachine.API) error {
swarmInfo := make(map[string]string)
w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
fmt.Fprintln(w, "NAME\tACTIVE\tDRIVER\tSTATE\tURL\tSWARM")
fmt.Fprintln(w, "NAME\tACTIVE\tDRIVER\tSTATE\tURL\tSWARM\tERRORS")
for _, host := range hostList {
swarmOptions := host.HostOptions.SwarmOptions
@ -98,8 +99,8 @@ func cmdLs(c CommandLine, api libmachine.API) error {
swarmInfo = fmt.Sprintf("%s (master)", swarmInfo)
}
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
item.Name, activeString, item.DriverName, item.State, item.URL, swarmInfo)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
item.Name, activeString, item.DriverName, item.State, item.URL, swarmInfo, item.Error)
}
w.Flush()
@ -231,36 +232,19 @@ func matchesName(host *host.Host, names []string) bool {
}
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
stateCh := make(chan state.State)
urlCh := make(chan string)
url := ""
hostError := ""
go func() {
currentState, err := h.Driver.GetState()
if err != nil {
log.Errorf("error getting state for host %s: %s", h.Name, err)
}
stateCh <- currentState
}()
go func() {
url, err := h.GetURL()
if err != nil {
if err.Error() == drivers.ErrHostIsNotRunning.Error() {
url = ""
} else {
log.Errorf("error getting URL for host %s: %s", h.Name, err)
}
}
urlCh <- url
}()
currentState := <-stateCh
url := <-urlCh
close(stateCh)
close(urlCh)
currentState, err := h.Driver.GetState()
if err == nil {
url, err = h.GetURL()
}
if err != nil {
hostError = err.Error()
}
if hostError == drivers.ErrHostIsNotRunning.Error() {
hostError = ""
}
stateQueryChan <- HostListItem{
Name: h.Name,
@ -269,6 +253,7 @@ func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
State: currentState,
URL: url,
SwarmOptions: h.HostOptions.SwarmOptions,
Error: hostError,
}
}

View File

@ -276,6 +276,7 @@ func TestFilterHostsDifferentFlagsProduceAND(t *testing.T) {
assert.EqualValues(t, filterHosts(hosts, opts), expected)
}
func captureStdout() (chan string, *os.File) {
r, w, _ := os.Pipe()
os.Stdout = w
@ -296,68 +297,58 @@ func TestGetHostListItems(t *testing.T) {
hosts := []*host.Host{
{
Name: "foo",
DriverName: "fakedriver",
Name: "foo",
Driver: &fakedriver.Driver{
MockState: state.Running,
},
HostOptions: &host.Options{
SwarmOptions: &swarm.Options{
Master: false,
Address: "",
Discovery: "",
},
SwarmOptions: &swarm.Options{},
},
},
{
Name: "bar",
DriverName: "fakedriver",
Name: "bar",
Driver: &fakedriver.Driver{
MockState: state.Stopped,
},
HostOptions: &host.Options{
SwarmOptions: &swarm.Options{
Master: false,
Address: "",
Discovery: "",
},
SwarmOptions: &swarm.Options{},
},
},
{
Name: "baz",
DriverName: "fakedriver",
Name: "baz",
Driver: &fakedriver.Driver{
MockState: state.Running,
MockState: state.Error,
},
HostOptions: &host.Options{
SwarmOptions: &swarm.Options{
Master: false,
Address: "",
Discovery: "",
},
SwarmOptions: &swarm.Options{},
},
},
}
expected := map[string]state.State{
"foo": state.Running,
"bar": state.Stopped,
"baz": state.Running,
expected := map[string]struct {
state state.State
active bool
error string
}{
"foo": {state.Running, true, ""},
"bar": {state.Stopped, false, ""},
"baz": {state.Error, false, "Unable to get url"},
}
items := []HostListItem{}
for _, host := range hosts {
go getHostState(host, hostListItemsChan)
}
for i := 0; i < len(hosts); i++ {
items = append(items, <-hostListItemsChan)
}
for _, item := range items {
if expected[item.Name] != item.State {
t.Fatal("Expected state did not match for item", item)
}
expected := expected[item.Name]
assert.Equal(t, expected.state, item.State)
assert.Equal(t, expected.active, item.Active)
assert.Equal(t, expected.error, item.Error)
}
}
@ -376,8 +367,7 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) {
hosts := []*host.Host{
{
Name: "foo",
DriverName: "fakedriver",
Name: "foo",
Driver: &fakedriver.Driver{
MockState: state.Running,
MockURL: "tcp://120.0.0.1:2376",
@ -391,8 +381,7 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) {
},
},
{
Name: "bar",
DriverName: "fakedriver",
Name: "bar",
Driver: &fakedriver.Driver{
MockState: state.Stopped,
},
@ -405,8 +394,7 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) {
},
},
{
Name: "baz",
DriverName: "fakedriver",
Name: "baz",
Driver: &fakedriver.Driver{
MockState: state.Saved,
},
@ -433,18 +421,15 @@ func TestGetHostListItemsEnvDockerHostUnset(t *testing.T) {
for _, host := range hosts {
go getHostState(host, hostListItemsChan)
}
for i := 0; i < len(hosts); i++ {
items = append(items, <-hostListItemsChan)
}
for _, item := range items {
if expected[item.Name].state != item.State {
t.Fatal("Expected state did not match for item", item)
}
if expected[item.Name].active != item.Active {
t.Fatal("Expected active flag did not match for item", item)
}
expected := expected[item.Name]
assert.Equal(t, expected.state, item.State)
assert.Equal(t, expected.active, item.Active)
}
}

View File

@ -1,6 +1,8 @@
package fakedriver
import (
"fmt"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/state"
@ -27,6 +29,12 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
}
func (d *Driver) GetURL() (string, error) {
if d.MockState == state.Error {
return "", fmt.Errorf("Unable to get url")
}
if d.MockState != state.Running {
return "", drivers.ErrHostIsNotRunning
}
return d.MockURL, nil
}