Skip to content

Commit ddbaef5

Browse files
committed
Merge pull request #3106 from johanneswuerbach/mange-all-units
feat(deisctl): start / stop all installed units
2 parents c6ec1eb + 751cc6b commit ddbaef5

13 files changed

Lines changed: 227 additions & 36 deletions

File tree

deisctl/Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ install:
3232
godep go install -v .
3333

3434
setup-root-gotools:
35-
sudo GOPATH=/tmp/tmpGOPATH go get -u -v code.google.com/p/go.tools/cmd/cover
36-
sudo GOPATH=/tmp/tmpGOPATH go get -u -v code.google.com/p/go.tools/cmd/vet
35+
sudo GOPATH=/tmp/tmpGOPATH go get -u -v golang.org/x/tools/cmd/cover
36+
sudo GOPATH=/tmp/tmpGOPATH go get -u -v golang.org/x/tools/cmd/vet
3737
sudo rm -rf /tmp/tmpGOPATH
3838

3939
setup-gotools:
40-
go get -v github.com/golang/lint/golint
40+
go get -u github.com/golang/lint/golint
41+
go get -u golang.org/x/tools/cmd/cover
42+
go get -u golang.org/x/tools/cmd/vet
4143

42-
test: test-style test-unit test-functional
44+
test: test-style test-unit
4345

4446
test-style:
4547
# display output, then check

deisctl/backend/fleet/destroy.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ import (
99

1010
// Destroy units for a given target
1111
func (c *FleetClient) Destroy(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
12-
for _, target := range targets {
12+
// expand @* targets
13+
expandedTargets, err := expandTargets(c, targets)
14+
if err != nil {
15+
errchan <- err
16+
return
17+
}
18+
19+
for _, target := range expandedTargets {
1320
wg.Add(1)
1421
go doDestroy(c, target, wg, outchan, errchan)
1522
}

deisctl/backend/fleet/start.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import (
1010

1111
// Start units and wait for their desiredState
1212
func (c *FleetClient) Start(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
13-
for _, target := range targets {
13+
// expand @* targets
14+
expandedTargets, err := expandTargets(c, targets)
15+
if err != nil {
16+
errchan <- err
17+
return
18+
}
19+
20+
for _, target := range expandedTargets {
1421
wg.Add(1)
1522
go doStart(c, target, wg, outchan, errchan)
1623
}

deisctl/backend/fleet/stop.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import (
1010

1111
// Stop units and wait for their desiredState
1212
func (c *FleetClient) Stop(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
13-
for _, target := range targets {
13+
// expand @* targets
14+
expandedTargets, err := expandTargets(c, targets)
15+
if err != nil {
16+
errchan <- err
17+
return
18+
}
19+
20+
for _, target := range expandedTargets {
1421
wg.Add(1)
1522
go doStop(c, target, wg, outchan, errchan)
1623
}

deisctl/backend/fleet/unit.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ func NewUnit(component string) (uf *unit.UnitFile, err error) {
7878
// formatUnitName returns a properly formatted systemd service name
7979
// using the given component type and number
8080
func formatUnitName(component string, num int) (unitName string, err error) {
81+
component = strings.TrimPrefix(component, "deis-")
8182
if num == 0 {
8283
return "deis-" + component + ".service", nil
8384
}

deisctl/backend/fleet/utils.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"regexp"
77
"sort"
88
"strconv"
9+
"strings"
910
"time"
1011
)
1112

@@ -66,10 +67,10 @@ func splitJobName(component string) (c string, num int, err error) {
6667

6768
func splitTarget(target string) (component string, num int, err error) {
6869
// see if we were provided a specific target
69-
r := regexp.MustCompile(`^([a-z-]+)(@\d+)?$`)
70+
r := regexp.MustCompile(`^([a-z-]+)(@\d+)?(\.service)?$`)
7071
match := r.FindStringSubmatch(target)
7172
// check for failed match
72-
if len(match) != 3 {
73+
if len(match) < 3 {
7374
err = fmt.Errorf("Could not parse target: %v", target)
7475
return
7576
}
@@ -84,6 +85,29 @@ func splitTarget(target string) (component string, num int, err error) {
8485
return match[1], num, err
8586
}
8687

88+
// expand a target to all installed units
89+
func expandTargets(c *FleetClient, targets []string) (expandedTargets []string, err error) {
90+
for _, t := range targets {
91+
if strings.HasSuffix(t, "@*") {
92+
var targets []string
93+
targets, err = expandTarget(c, strings.TrimSuffix(t, "@*"))
94+
if err != nil {
95+
return
96+
}
97+
expandedTargets = append(expandedTargets, targets...)
98+
} else {
99+
expandedTargets = append(expandedTargets, t)
100+
}
101+
102+
}
103+
return
104+
}
105+
106+
func expandTarget(c *FleetClient, target string) (targets []string, err error) {
107+
targets, err = c.Units(target)
108+
return
109+
}
110+
87111
// randomValue returns a random string from a slice of string
88112
func randomValue(src []string) string {
89113
s := rand.NewSource(int64(time.Now().Unix()))

deisctl/backend/fleet/utils_test.go

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package fleet
22

3-
import "testing"
3+
import (
4+
"fmt"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/coreos/fleet/machine"
9+
"github.com/coreos/fleet/schema"
10+
)
411

512
func TestNextComponent(t *testing.T) {
613
// test first component
@@ -87,3 +94,66 @@ func TestSplitTarget(t *testing.T) {
8794
}
8895

8996
}
97+
98+
type stubFleetClient struct{}
99+
100+
var (
101+
units []*schema.Unit
102+
)
103+
104+
func (c stubFleetClient) Machines() ([]machine.MachineState, error) {
105+
return []machine.MachineState{}, nil
106+
}
107+
func (c stubFleetClient) Unit(string) (*schema.Unit, error) {
108+
return nil, nil
109+
}
110+
func (c stubFleetClient) Units() ([]*schema.Unit, error) {
111+
return units, nil
112+
}
113+
func (c stubFleetClient) UnitStates() ([]*schema.UnitState, error) {
114+
return []*schema.UnitState{}, nil
115+
}
116+
func (c stubFleetClient) SetUnitTargetState(name, target string) error {
117+
return fmt.Errorf("SetUnitTargetState not implemented yet.")
118+
}
119+
func (c stubFleetClient) CreateUnit(*schema.Unit) error {
120+
return fmt.Errorf("CreateUnit not implemented yet.")
121+
}
122+
func (c stubFleetClient) DestroyUnit(string) error {
123+
return fmt.Errorf("DestroyUnit not implemented yet.")
124+
}
125+
126+
var fc stubFleetClient
127+
128+
func TestExpandTargets(t *testing.T) {
129+
units = []*schema.Unit{
130+
&schema.Unit{
131+
Name: "deis-router@1.service",
132+
},
133+
&schema.Unit{
134+
Name: "deis-router@2.service",
135+
},
136+
&schema.Unit{
137+
Name: "deis-store-gateway@1.service",
138+
},
139+
&schema.Unit{
140+
Name: "deis-controller.service",
141+
},
142+
}
143+
c := &FleetClient{Fleet: fc}
144+
145+
targets := []string{"deis-router@*", "deis-store-gateway@1", "deis-controller"}
146+
expandedTargets, err := expandTargets(c, targets)
147+
if err != nil {
148+
t.Fatal(err)
149+
}
150+
expectedTargets := []string{
151+
"deis-router@1.service",
152+
"deis-router@2.service",
153+
"deis-store-gateway@1",
154+
"deis-controller",
155+
}
156+
if !reflect.DeepEqual(expandedTargets, expectedTargets) {
157+
t.Fatal(expandedTargets)
158+
}
159+
}

deisctl/cmd/cmd.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ func startDefaultServices(b backend.Backend, wg *sync.WaitGroup, outchan chan st
171171
wg.Wait()
172172

173173
// we start gateway first to give metadata time to come up for volume
174-
b.Start([]string{"store-gateway@1"}, wg, outchan, errchan)
174+
b.Start([]string{"store-gateway@*"}, wg, outchan, errchan)
175175
wg.Wait()
176176
b.Start([]string{"store-volume"}, wg, outchan, errchan)
177177
wg.Wait()
@@ -188,12 +188,12 @@ func startDefaultServices(b backend.Backend, wg *sync.WaitGroup, outchan chan st
188188
b.Start([]string{"cache"}, &_wg, _outchan, _errchan)
189189
wg.Wait()
190190
b.Start([]string{
191-
"database", "registry@1", "controller", "builder",
192-
"publisher", "router@1", "router@2", "router@3"},
191+
"database", "registry@*", "controller", "builder",
192+
"publisher", "router@*"},
193193
&_wg, _outchan, _errchan)
194194

195195
outchan <- fmt.Sprintf("Control plane...")
196-
b.Start([]string{"cache", "database", "registry@1", "controller"}, wg, outchan, errchan)
196+
b.Start([]string{"cache", "database", "registry@*", "controller"}, wg, outchan, errchan)
197197
wg.Wait()
198198
b.Start([]string{"builder"}, wg, outchan, errchan)
199199
wg.Wait()
@@ -203,7 +203,7 @@ func startDefaultServices(b backend.Backend, wg *sync.WaitGroup, outchan chan st
203203
wg.Wait()
204204

205205
outchan <- fmt.Sprintf("Routing mesh...")
206-
b.Start([]string{"router@1", "router@2", "router@3"}, wg, outchan, errchan)
206+
b.Start([]string{"router@*"}, wg, outchan, errchan)
207207
wg.Wait()
208208
}
209209

@@ -264,15 +264,15 @@ func StopPlatform(b backend.Backend) error {
264264
func stopDefaultServices(b backend.Backend, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
265265

266266
outchan <- fmt.Sprintf("Routing mesh...")
267-
b.Stop([]string{"router@1", "router@2", "router@3"}, wg, outchan, errchan)
267+
b.Stop([]string{"router@*"}, wg, outchan, errchan)
268268
wg.Wait()
269269

270270
outchan <- fmt.Sprintf("Data plane...")
271271
b.Stop([]string{"publisher"}, wg, outchan, errchan)
272272
wg.Wait()
273273

274274
outchan <- fmt.Sprintf("Control plane...")
275-
b.Stop([]string{"controller", "builder", "database", "registry@1"}, wg, outchan, errchan)
275+
b.Stop([]string{"controller", "builder", "database", "registry@*"}, wg, outchan, errchan)
276276
wg.Wait()
277277
b.Stop([]string{"cache"}, wg, outchan, errchan)
278278
wg.Wait()
@@ -282,7 +282,7 @@ func stopDefaultServices(b backend.Backend, wg *sync.WaitGroup, outchan chan str
282282
wg.Wait()
283283

284284
outchan <- fmt.Sprintf("Storage subsystem...")
285-
b.Stop([]string{"store-volume", "store-gateway@1"}, wg, outchan, errchan)
285+
b.Stop([]string{"store-volume", "store-gateway@*"}, wg, outchan, errchan)
286286
wg.Wait()
287287
b.Stop([]string{"store-metadata"}, wg, outchan, errchan)
288288
wg.Wait()
@@ -508,23 +508,23 @@ func UninstallPlatform(b backend.Backend) error {
508508
func uninstallAllServices(b backend.Backend, wg *sync.WaitGroup, outchan chan string, errchan chan error) error {
509509

510510
outchan <- fmt.Sprintf("Routing mesh...")
511-
b.Destroy([]string{"router@1", "router@2", "router@3"}, wg, outchan, errchan)
511+
b.Destroy([]string{"router@*"}, wg, outchan, errchan)
512512
wg.Wait()
513513

514514
outchan <- fmt.Sprintf("Data plane...")
515515
b.Destroy([]string{"publisher"}, wg, outchan, errchan)
516516
wg.Wait()
517517

518518
outchan <- fmt.Sprintf("Control plane...")
519-
b.Destroy([]string{"controller", "builder", "cache", "database", "registry@1"}, wg, outchan, errchan)
519+
b.Destroy([]string{"controller", "builder", "cache", "database", "registry@*"}, wg, outchan, errchan)
520520
wg.Wait()
521521

522522
outchan <- fmt.Sprintf("Logging subsystem...")
523523
b.Destroy([]string{"logger", "logspout"}, wg, outchan, errchan)
524524
wg.Wait()
525525

526526
outchan <- fmt.Sprintf("Storage subsystem...")
527-
b.Destroy([]string{"store-volume", "store-gateway@1"}, wg, outchan, errchan)
527+
b.Destroy([]string{"store-volume", "store-gateway@*"}, wg, outchan, errchan)
528528
wg.Wait()
529529
b.Destroy([]string{"store-metadata"}, wg, outchan, errchan)
530530
wg.Wait()

deisctl/cmd/cmd_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"sync"
7+
"testing"
8+
)
9+
10+
type stubBackend struct{}
11+
12+
var (
13+
startedUnits []string
14+
stoppedUnits []string
15+
installedUnits []string
16+
)
17+
18+
func (backend stubBackend) Create([]string, *sync.WaitGroup, chan string, chan error) {
19+
return
20+
}
21+
func (backend stubBackend) Destroy([]string, *sync.WaitGroup, chan string, chan error) {
22+
return
23+
}
24+
func (backend stubBackend) Start(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
25+
startedUnits = targets
26+
return
27+
}
28+
func (backend stubBackend) Stop(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
29+
stoppedUnits = targets
30+
return
31+
}
32+
func (backend stubBackend) Scale(string, int, *sync.WaitGroup, chan string, chan error) {
33+
return
34+
}
35+
func (backend stubBackend) ListUnits() error {
36+
return fmt.Errorf("ListUnits not implemented yet.")
37+
}
38+
func (backend stubBackend) ListUnitFiles() error {
39+
return fmt.Errorf("ListUnitFiles not implemented yet.")
40+
}
41+
func (backend stubBackend) Status(string) error {
42+
return fmt.Errorf("Status not implemented yet.")
43+
}
44+
func (backend stubBackend) Journal(string) error {
45+
return fmt.Errorf("Journal not implemented yet.")
46+
}
47+
48+
var b stubBackend
49+
50+
// Start units
51+
func TestStart(t *testing.T) {
52+
Start([]string{"start", "router@1", "router@2"}, b)
53+
54+
if !reflect.DeepEqual(startedUnits, []string{"router@1", "router@2"}) {
55+
t.Error(startedUnits)
56+
}
57+
}
58+
59+
// Stop units
60+
func TestStop(t *testing.T) {
61+
Stop([]string{"stop", "router@1", "router@2"}, b)
62+
63+
if !reflect.DeepEqual(stoppedUnits, []string{"router@1", "router@2"}) {
64+
t.Error(stoppedUnits)
65+
}
66+
}
67+
68+
// Restart units
69+
func TestRestart(t *testing.T) {
70+
Restart([]string{"restart", "router@4", "router@5"}, b)
71+
72+
if !reflect.DeepEqual(stoppedUnits, []string{"router@4", "router@5"}) {
73+
t.Error(stoppedUnits)
74+
}
75+
if !reflect.DeepEqual(startedUnits, []string{"router@4", "router@5"}) {
76+
t.Error(startedUnits)
77+
}
78+
}

deisctl/utils/utils.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// Package utils contains commonly useful functions from Deisctl
2-
32
package utils
43

54
import (

0 commit comments

Comments
 (0)