/
multi_service.go
140 lines (118 loc) · 3.54 KB
/
multi_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package connect
import (
"fmt"
"strings"
"time"
consulapi "github.com/hashicorp/consul/api"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/e2e/framework"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/jobspec"
"github.com/hashicorp/nomad/testutil"
"github.com/kr/pretty"
"github.com/stretchr/testify/require"
)
// TestMultiServiceConnect tests running multiple envoy sidecars in the same allocation.
func (tc *ConnectE2ETest) TestMultiServiceConnect(f *framework.F) {
t := f.T()
uuid := uuid.Generate()
jobID := "connect" + uuid[0:8]
tc.jobIds = append(tc.jobIds, jobID)
jobapi := tc.Nomad().Jobs()
job, err := jobspec.ParseFile("connect/input/multi-service.nomad")
require.NoError(t, err)
job.ID = &jobID
resp, _, err := jobapi.Register(job, nil)
require.NoError(t, err)
require.NotNil(t, resp)
require.Zero(t, resp.Warnings)
EVAL:
qopts := &api.QueryOptions{
WaitIndex: resp.EvalCreateIndex,
}
evalapi := tc.Nomad().Evaluations()
eval, qmeta, err := evalapi.Info(resp.EvalID, qopts)
require.NoError(t, err)
qopts.WaitIndex = qmeta.LastIndex
switch eval.Status {
case "pending":
goto EVAL
case "complete":
// Ok!
case "failed", "canceled", "blocked":
require.Failf(t, "expected complete status", "eval %s\n%s", eval.Status, pretty.Sprint(eval))
default:
require.Failf(t, "expected complete status", "unknown eval status: %s\n%s", eval.Status, pretty.Sprint(eval))
}
// Assert there were 0 placement failures
require.Zero(t, eval.FailedTGAllocs, pretty.Sprint(eval.FailedTGAllocs))
require.Len(t, eval.QueuedAllocations, 1, pretty.Sprint(eval.QueuedAllocations))
// Assert allocs are running
for i := 0; i < 20; i++ {
allocs, qmeta, err := evalapi.Allocations(eval.ID, qopts)
require.NoError(t, err)
require.Len(t, allocs, 1)
qopts.WaitIndex = qmeta.LastIndex
running := 0
for _, alloc := range allocs {
switch alloc.ClientStatus {
case "running":
running++
case "pending":
// keep trying
default:
require.Failf(t, "alloc failed", "alloc: %s", pretty.Sprint(alloc))
}
}
if running == len(allocs) {
break
}
time.Sleep(500 * time.Millisecond)
}
allocs, _, err := evalapi.Allocations(eval.ID, qopts)
require.NoError(t, err)
allocIDs := make(map[string]bool, 1)
for _, a := range allocs {
if a.ClientStatus != "running" || a.DesiredStatus != "run" {
require.Failf(t, "expected running status", "alloc %s (%s) terminal; client=%s desired=%s", a.TaskGroup, a.ID, a.ClientStatus, a.DesiredStatus)
}
allocIDs[a.ID] = true
}
// Check Consul service health
agentapi := tc.Consul().Agent()
failing := map[string]*consulapi.AgentCheck{}
testutil.WaitForResultRetries(60, func() (bool, error) {
defer time.Sleep(time.Second)
checks, err := agentapi.Checks()
require.NoError(t, err)
// Filter out checks for other services
for cid, check := range checks {
found := false
for allocID := range allocIDs {
if strings.Contains(check.ServiceID, allocID) {
found = true
break
}
}
if !found {
delete(checks, cid)
}
}
// Ensure checks are all passing
failing = map[string]*consulapi.AgentCheck{}
for _, check := range checks {
if check.Status != "passing" {
failing[check.CheckID] = check
break
}
}
if len(failing) == 0 {
return true, nil
}
t.Logf("still %d checks not passing", len(failing))
return false, fmt.Errorf("checks are not passing %v %v", len(failing), pretty.Sprint(failing))
}, func(e error) {
require.NoError(t, err)
})
require.Len(t, failing, 0, pretty.Sprint(failing))
}