Skip to content

Commit 4bd8ceb

Browse files
committed
Merge pull request #3887 from Joshua-Anderson/backend-testing
tests(deisctl): Add tests to backend package
2 parents 11a6698 + 40d6b02 commit 4bd8ceb

26 files changed

Lines changed: 1326 additions & 137 deletions

deisctl/backend/fleet/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (c *FleetClient) createServiceUnit(component string, num int) (name string,
9292
if err != nil {
9393
return "", nil, err
9494
}
95-
uf, err = NewUnit(component)
95+
uf, err = NewUnit(component, c.templatePaths)
9696
if err != nil {
9797
return
9898
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package fleet
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"path"
7+
"sync"
8+
"testing"
9+
10+
"github.com/coreos/fleet/schema"
11+
)
12+
13+
func TestCreate(t *testing.T) {
14+
15+
unitFiles := []string{"deis-controller.service", "deis-builder.service",
16+
"deis-router.service"}
17+
18+
unitContents := []byte("[Unit]")
19+
20+
name, err := ioutil.TempDir("", "deisctl-fleetctl")
21+
22+
if err != nil {
23+
t.Fatal(err)
24+
}
25+
26+
for _, unit := range unitFiles {
27+
ioutil.WriteFile(path.Join(name, unit), unitContents, 777)
28+
}
29+
30+
testFleetClient := stubFleetClient{testUnits: []*schema.Unit{}, unitsMutex: &sync.Mutex{},
31+
unitStatesMutex: &sync.Mutex{}}
32+
33+
c := &FleetClient{templatePaths: []string{name}, Fleet: &testFleetClient}
34+
35+
var errOutput string
36+
outchan := make(chan string)
37+
errchan := make(chan error)
38+
var wg sync.WaitGroup
39+
40+
logMutex := sync.Mutex{}
41+
42+
go logState(outchan, errchan, &errOutput, &logMutex)
43+
44+
c.Create([]string{"controller", "builder", "router@1"}, &wg, outchan, errchan)
45+
46+
wg.Wait()
47+
close(errchan)
48+
close(outchan)
49+
50+
logMutex.Lock()
51+
if errOutput != "" {
52+
t.Fatal(errOutput)
53+
}
54+
logMutex.Unlock()
55+
56+
expectedUnits := []string{"deis-controller.service", "deis-builder.service",
57+
"deis-router@1.service"}
58+
59+
for _, expectedUnit := range expectedUnits {
60+
found := false
61+
62+
for _, unit := range testFleetClient.testUnits {
63+
if unit.Name == expectedUnit {
64+
found = true
65+
break
66+
}
67+
}
68+
69+
if !found {
70+
t.Error(fmt.Errorf("Expected Unit %s not found in Unit States", expectedUnit))
71+
}
72+
}
73+
}

deisctl/backend/fleet/destroy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
// Destroy units for a given target
1111
func (c *FleetClient) Destroy(targets []string, wg *sync.WaitGroup, outchan chan string, errchan chan error) {
1212
// expand @* targets
13-
expandedTargets, err := expandTargets(c, targets)
13+
expandedTargets, err := c.expandTargets(targets)
1414
if err != nil {
1515
errchan <- err
1616
return
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package fleet
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
"testing"
7+
8+
"github.com/coreos/fleet/schema"
9+
)
10+
11+
func TestDestroy(t *testing.T) {
12+
testUnits := []*schema.Unit{
13+
&schema.Unit{
14+
Name: "deis-registry.service",
15+
},
16+
&schema.Unit{
17+
Name: "deis-builder.service",
18+
},
19+
&schema.Unit{
20+
Name: "deis-router@1.service",
21+
},
22+
}
23+
24+
testFleetClient := stubFleetClient{testUnits: testUnits, testUnitStates: []*schema.UnitState{}, unitsMutex: &sync.Mutex{}, unitStatesMutex: &sync.Mutex{}}
25+
26+
c := &FleetClient{Fleet: &testFleetClient}
27+
28+
var errOutput string
29+
outchan := make(chan string)
30+
errchan := make(chan error)
31+
var wg sync.WaitGroup
32+
33+
logMutex := sync.Mutex{}
34+
35+
go logState(outchan, errchan, &errOutput, &logMutex)
36+
37+
c.Destroy([]string{"controller", "registry", "router@1"}, &wg, outchan, errchan)
38+
39+
wg.Wait()
40+
close(errchan)
41+
close(outchan)
42+
43+
logMutex.Lock()
44+
if errOutput != "" {
45+
t.Fatal(errOutput)
46+
}
47+
logMutex.Unlock()
48+
49+
if len(testFleetClient.testUnits) != 1 || testFleetClient.testUnits[0].Name != "deis-builder.service" {
50+
t.Error(fmt.Errorf("Got %d Units (want 1), first unit %s (want builder)", len(testFleetClient.testUnits), testFleetClient.testUnits[0].Name))
51+
}
52+
}

deisctl/backend/fleet/fleet.go

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

33
import (
4+
"io"
5+
"os"
6+
"path"
7+
"text/tabwriter"
8+
49
"github.com/coreos/fleet/client"
510
"github.com/coreos/fleet/machine"
611
)
@@ -11,6 +16,11 @@ type FleetClient struct {
1116

1217
// used to cache MachineStates
1318
machineStates map[string]*machine.MachineState
19+
20+
templatePaths []string
21+
runner commandRunner
22+
out *tabwriter.Writer
23+
errWriter io.Writer
1424
}
1525

1626
// NewClient returns a client used to communicate with Fleet
@@ -20,5 +30,17 @@ func NewClient() (*FleetClient, error) {
2030
if err != nil {
2131
return nil, err
2232
}
23-
return &FleetClient{Fleet: client}, nil
33+
34+
// path hierarchy for finding systemd service templates
35+
templatePaths := []string{
36+
os.Getenv("DEISCTL_UNITS"),
37+
path.Join(os.Getenv("HOME"), ".deis", "units"),
38+
"/var/lib/deis/units",
39+
}
40+
41+
out := new(tabwriter.Writer)
42+
out.Init(os.Stdout, 0, 8, 1, '\t', 0)
43+
44+
return &FleetClient{Fleet: client, templatePaths: templatePaths, runner: sshCommandRunner{},
45+
out: out, errWriter: os.Stderr}, nil
2446
}

deisctl/backend/fleet/fleet_test.go

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

3-
import "testing"
3+
import (
4+
"fmt"
5+
"sync"
6+
"testing"
7+
8+
"github.com/coreos/fleet/machine"
9+
"github.com/coreos/fleet/schema"
10+
)
11+
12+
type stubFleetClient struct {
13+
testUnits []*schema.Unit
14+
testUnitStates []*schema.UnitState
15+
testMachineStates []machine.MachineState
16+
unitStatesMutex *sync.Mutex
17+
unitsMutex *sync.Mutex
18+
}
19+
20+
func (c *stubFleetClient) Machines() ([]machine.MachineState, error) {
21+
return c.testMachineStates, nil
22+
}
23+
func (c *stubFleetClient) Unit(name string) (*schema.Unit, error) {
24+
c.unitsMutex.Lock()
25+
defer c.unitsMutex.Unlock()
26+
27+
for _, unit := range c.testUnits {
28+
if unit.Name == name {
29+
return unit, nil
30+
}
31+
}
32+
33+
return nil, fmt.Errorf("Unit %s not found", name)
34+
}
35+
func (c *stubFleetClient) Units() ([]*schema.Unit, error) {
36+
c.unitsMutex.Lock()
37+
defer c.unitsMutex.Unlock()
38+
39+
return c.testUnits, nil
40+
}
41+
func (c *stubFleetClient) UnitStates() ([]*schema.UnitState, error) {
42+
c.unitStatesMutex.Lock()
43+
defer c.unitStatesMutex.Unlock()
44+
45+
return c.testUnitStates, nil
46+
}
47+
func (c *stubFleetClient) SetUnitTargetState(name, target string) error {
48+
49+
var activeState string
50+
var subState string
51+
52+
if target == "loaded" {
53+
activeState = "inactive"
54+
subState = "dead"
55+
} else if target == "launched" {
56+
activeState = "active"
57+
subState = "running"
58+
}
59+
60+
unit, err := c.Unit(name)
61+
62+
if err != nil {
63+
return err
64+
}
65+
66+
c.unitsMutex.Lock()
67+
unit.DesiredState = target
68+
c.unitsMutex.Unlock()
69+
70+
c.unitStatesMutex.Lock()
71+
defer c.unitStatesMutex.Unlock()
72+
73+
for _, unitState := range c.testUnitStates {
74+
if name == unitState.Name {
75+
unitState.SystemdSubState = subState
76+
unitState.SystemdActiveState = activeState
77+
return nil
78+
}
79+
}
80+
81+
c.testUnitStates = append(c.testUnitStates, &schema.UnitState{Name: name, SystemdSubState: subState, SystemdActiveState: activeState})
82+
83+
return nil
84+
}
85+
86+
func (c *stubFleetClient) CreateUnit(unit *schema.Unit) error {
87+
c.unitsMutex.Lock()
88+
c.testUnits = append(c.testUnits, unit)
89+
c.unitsMutex.Unlock()
90+
91+
return nil
92+
}
93+
94+
func (c *stubFleetClient) DestroyUnit(name string) error {
95+
c.unitsMutex.Lock()
96+
for i := len(c.testUnits) - 1; i >= 0; i-- {
97+
if c.testUnits[i].Name == name {
98+
c.testUnits = append(c.testUnits[:i], c.testUnits[i+1:]...)
99+
}
100+
}
101+
c.unitsMutex.Unlock()
102+
103+
return nil
104+
}
105+
106+
func logState(outchan chan string, errchan chan error, errOutput *string, mutex *sync.Mutex) {
107+
for {
108+
select {
109+
case _, ok := <-outchan:
110+
if !ok {
111+
outchan = nil
112+
}
113+
case err, ok := <-errchan:
114+
if !ok {
115+
errchan = nil
116+
}
117+
if err != nil {
118+
mutex.Lock()
119+
*errOutput += fmt.Sprintf("%v\n", err)
120+
mutex.Unlock()
121+
}
122+
}
123+
if outchan == nil && errchan == nil {
124+
break
125+
}
126+
}
127+
}
4128

5129
func TestNewClient(t *testing.T) {
6130
// set required flags

deisctl/backend/fleet/journal.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ func (c *FleetClient) Journal(target string) (err error) {
1111
return
1212
}
1313
for _, unit := range units {
14-
runJournal(c, unit)
14+
c.runJournal(unit)
1515
}
1616
return
1717
}
1818

1919
// runJournal tails the systemd journal for a given unit
20-
func runJournal(c *FleetClient, name string) (exit int) {
21-
machineID, err := findUnit(c, name)
20+
func (c *FleetClient) runJournal(name string) (exit int) {
21+
machineID, err := c.findUnit(name)
2222

2323
if err != nil {
2424
return 1
2525
}
2626

2727
command := fmt.Sprintf("journalctl --unit %s --no-pager -n 40 -f", name)
28-
return runCommand(c, command, machineID)
28+
return c.runCommand(command, machineID)
2929
}

0 commit comments

Comments
 (0)