Skip to content

Commit 8a672ad

Browse files
committed
Merge pull request #4095 from technosophos/issue/3880-fix-deisctl-hangs
fix(deisctl): exit when stop/start fails
2 parents ff73695 + 859c792 commit 8a672ad

5 files changed

Lines changed: 104 additions & 41 deletions

File tree

deisctl/backend/fleet/fleet_test.go

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ func (c *stubFleetClient) UnitStates() ([]*schema.UnitState, error) {
4545

4646
return c.testUnitStates, nil
4747
}
48+
49+
type failingFleetClient struct {
50+
stubFleetClient
51+
}
52+
53+
func (c *failingFleetClient) SetUnitTargetState(name, target string) error {
54+
if err := c.stubFleetClient.SetUnitTargetState(name, target); err != nil {
55+
return err
56+
}
57+
58+
last := len(c.testUnitStates) - 1
59+
c.testUnitStates[last] = &schema.UnitState{
60+
Name: name,
61+
SystemdSubState: "failed",
62+
SystemdActiveState: "failed",
63+
}
64+
65+
return nil
66+
}
67+
4868
func (c *stubFleetClient) SetUnitTargetState(name, target string) error {
4969

5070
var activeState string
@@ -149,31 +169,6 @@ func (s *syncBuffer) Bytes() []byte {
149169
return s.Buffer.Bytes()
150170
}
151171

152-
/*
153-
func logState(outchan chan string, errchan chan error, errOutput *string, mutex *sync.Mutex) {
154-
for {
155-
select {
156-
case _, ok := <-outchan:
157-
if !ok {
158-
outchan = nil
159-
}
160-
case err, ok := <-errchan:
161-
if !ok {
162-
errchan = nil
163-
}
164-
if err != nil {
165-
mutex.Lock()
166-
*errOutput += err.Error()
167-
mutex.Unlock()
168-
}
169-
}
170-
if outchan == nil && errchan == nil {
171-
break
172-
}
173-
}
174-
}
175-
*/
176-
177172
func TestNewClient(t *testing.T) {
178173
t.Parallel()
179174

deisctl/backend/fleet/start.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ func doStart(c *FleetClient, target string, wg *sync.WaitGroup, out, ew io.Write
8686
}
8787

8888
lastSubState = currentState.SystemdSubState
89+
90+
if lastSubState == "failed" {
91+
o := prettyprint.Colorize("{{.Red}}The service '%s' failed while starting.{{.Default}}\n")
92+
fmt.Fprintf(ew, o, target)
93+
return
94+
}
8995
time.Sleep(250 * time.Millisecond)
9096
}
9197
}

deisctl/backend/fleet/start_test.go

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
package fleet
22

33
import (
4+
"strings"
45
"sync"
56
"testing"
67

78
"github.com/coreos/fleet/schema"
89
)
910

11+
var startTestUnits = []*schema.Unit{
12+
&schema.Unit{
13+
Name: "deis-controller.service",
14+
DesiredState: "loaded",
15+
},
16+
&schema.Unit{
17+
Name: "deis-builder.service",
18+
DesiredState: "loaded",
19+
},
20+
&schema.Unit{
21+
Name: "deis-publisher.service",
22+
DesiredState: "loaded",
23+
},
24+
}
25+
1026
func TestStart(t *testing.T) {
1127
t.Parallel()
1228

13-
testUnits := []*schema.Unit{
14-
&schema.Unit{
15-
Name: "deis-controller.service",
16-
DesiredState: "loaded",
17-
},
18-
&schema.Unit{
19-
Name: "deis-builder.service",
20-
DesiredState: "loaded",
21-
},
22-
&schema.Unit{
23-
Name: "deis-publisher.service",
24-
DesiredState: "loaded",
25-
},
26-
}
27-
28-
testFleetClient := stubFleetClient{testUnits: testUnits,
29+
testFleetClient := stubFleetClient{testUnits: startTestUnits,
2930
unitsMutex: &sync.Mutex{}, unitStatesMutex: &sync.Mutex{}}
3031

3132
c := &FleetClient{Fleet: &testFleetClient}
@@ -68,3 +69,22 @@ func TestStart(t *testing.T) {
6869
}
6970
}
7071
}
72+
73+
func TestStartFail(t *testing.T) {
74+
fc := &failingFleetClient{stubFleetClient{
75+
testUnits: startTestUnits,
76+
unitStatesMutex: &sync.Mutex{},
77+
unitsMutex: &sync.Mutex{},
78+
}}
79+
var wg sync.WaitGroup
80+
c := &FleetClient{Fleet: fc}
81+
82+
var b syncBuffer
83+
c.Start([]string{"deis-builder.service"}, &wg, &b, &b)
84+
wg.Wait()
85+
86+
if !strings.Contains(b.String(), "failed while starting") {
87+
t.Errorf("Expected failure during start. Got '%s'", b.String())
88+
}
89+
90+
}

deisctl/backend/fleet/stop.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ func doStop(c *FleetClient, target string, wg *sync.WaitGroup, out, ew io.Writer
8888
}
8989

9090
lastSubState = currentState.SystemdSubState
91+
92+
if lastSubState == "failed" {
93+
o := prettyprint.Colorize("{{.Red}}The service '%s' failed while stopping.{{.Default}}\n")
94+
fmt.Fprintf(ew, o, target)
95+
return
96+
}
97+
9198
time.Sleep(250 * time.Millisecond)
9299
}
93100
}

deisctl/backend/fleet/stop_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fleet
22

33
import (
4+
"strings"
45
"sync"
56
"testing"
67

@@ -68,3 +69,37 @@ func TestStop(t *testing.T) {
6869
}
6970
}
7071
}
72+
73+
var stopTestUnits = []*schema.Unit{
74+
&schema.Unit{
75+
Name: "deis-controller.service",
76+
DesiredState: "launched",
77+
},
78+
&schema.Unit{
79+
Name: "deis-builder.service",
80+
DesiredState: "launched",
81+
},
82+
&schema.Unit{
83+
Name: "deis-publisher.service",
84+
DesiredState: "launch",
85+
},
86+
}
87+
88+
func TestStopFail(t *testing.T) {
89+
fc := &failingFleetClient{stubFleetClient{
90+
testUnits: stopTestUnits,
91+
unitStatesMutex: &sync.Mutex{},
92+
unitsMutex: &sync.Mutex{},
93+
}}
94+
var wg sync.WaitGroup
95+
c := &FleetClient{Fleet: fc}
96+
97+
var b syncBuffer
98+
c.Stop([]string{"deis-builder.service"}, &wg, &b, &b)
99+
wg.Wait()
100+
101+
if !strings.Contains(b.String(), "failed while stopping") {
102+
t.Errorf("Expected 'failed while stopping'. Got '%s'", b.String())
103+
}
104+
105+
}

0 commit comments

Comments
 (0)