1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
12 "git.curoverse.com/arvados.git/lib/cloud"
13 "git.curoverse.com/arvados.git/lib/dispatchcloud/test"
14 "git.curoverse.com/arvados.git/sdk/go/arvados"
15 "github.com/sirupsen/logrus"
16 check "gopkg.in/check.v1"
19 var _ = check.Suite(&WorkerSuite{})
21 type WorkerSuite struct{}
23 func (suite *WorkerSuite) TestProbeAndUpdate(c *check.C) {
24 logger := logrus.StandardLogger()
25 bootTimeout := time.Minute
26 probeTimeout := time.Second
28 is, err := (&test.StubDriver{}).InstanceSet(nil, "", logger)
29 c.Assert(err, check.IsNil)
30 inst, err := is.Create(arvados.InstanceType{}, "", nil, nil)
31 c.Assert(err, check.IsNil)
34 testCaseComment string // displayed in test output to help identify failure case
39 respBoot stubResp // zero value is success
40 respRun stubResp // zero value is success + nothing running
45 errFail := errors.New("failed")
46 respFail := stubResp{"", "command failed\n", errFail}
47 respContainerRunning := stubResp{"zzzzz-dz642-abcdefghijklmno\n", "", nil}
48 for _, trial := range []trialT{
50 testCaseComment: "Unknown, probes fail",
54 expectState: StateUnknown,
57 testCaseComment: "Unknown, boot probe fails, but one container is running",
60 respRun: respContainerRunning,
61 expectState: StateUnknown,
65 testCaseComment: "Unknown, boot probe fails, previously running container has exited",
69 expectState: StateUnknown,
73 testCaseComment: "Unknown, boot timeout exceeded, boot probe fails",
75 age: bootTimeout + time.Second,
78 expectState: StateShutdown,
81 testCaseComment: "Unknown, boot timeout exceeded, boot probe succeeds but crunch-run fails",
85 expectState: StateShutdown,
88 testCaseComment: "Unknown, boot timeout exceeded, boot probe fails but crunch-run succeeds",
92 expectState: StateShutdown,
95 testCaseComment: "Unknown, boot timeout exceeded, boot probe fails but container is running",
99 respRun: respContainerRunning,
100 expectState: StateUnknown,
104 testCaseComment: "Booting, boot probe fails, run probe fails",
108 expectState: StateBooting,
111 testCaseComment: "Booting, boot probe fails, run probe succeeds (but isn't expected to be called)",
114 expectState: StateBooting,
117 testCaseComment: "Booting, boot probe succeeds, run probe fails",
120 expectState: StateBooting,
123 testCaseComment: "Booting, boot probe succeeds, run probe succeeds",
125 expectState: StateIdle,
128 testCaseComment: "Booting, boot probe succeeds, run probe succeeds, container is running",
130 respRun: respContainerRunning,
131 expectState: StateRunning,
135 testCaseComment: "Booting, boot timeout exceeded",
137 age: bootTimeout * 2,
139 expectState: StateShutdown,
142 testCaseComment: "Idle, probe timeout exceeded, one container running",
144 age: probeTimeout * 2,
145 respRun: respContainerRunning,
146 expectState: StateRunning,
150 testCaseComment: "Idle, probe timeout exceeded, one container running, probe fails",
152 age: probeTimeout * 2,
155 expectState: StateShutdown,
159 testCaseComment: "Idle, probe timeout exceeded, nothing running, probe fails",
161 age: probeTimeout * 2,
163 expectState: StateShutdown,
166 testCaseComment: "Running, one container still running",
169 respRun: respContainerRunning,
170 expectState: StateRunning,
174 testCaseComment: "Running, container has exited",
177 expectState: StateIdle,
181 testCaseComment: "Running, probe timeout exceeded, nothing running, new container being started",
183 age: probeTimeout * 2,
185 expectState: StateRunning,
188 c.Logf("------- %#v", trial)
189 ctime := time.Now().Add(-trial.age)
191 "bootprobe": trial.respBoot,
192 "crunch-run --list": trial.respRun,
195 newExecutor: func(cloud.Instance) Executor { return exr },
196 bootProbeCommand: "bootprobe",
197 timeoutBooting: bootTimeout,
198 timeoutProbe: probeTimeout,
199 exited: map[string]time.Time{},
213 if trial.running > 0 {
214 wkr.running = map[string]struct{}{"zzzzz-dz642-abcdefghijklmno": struct{}{}}
216 if trial.starting > 0 {
217 wkr.starting = map[string]struct{}{"zzzzz-dz642-abcdefghijklmno": struct{}{}}
220 c.Check(wkr.state, check.Equals, trial.expectState)
221 c.Check(len(wkr.running), check.Equals, trial.expectRunning)
225 type stubResp struct {
230 type stubExecutor map[string]stubResp
232 func (se stubExecutor) SetTarget(cloud.ExecutorTarget) {}
233 func (se stubExecutor) Close() {}
234 func (se stubExecutor) Execute(env map[string]string, cmd string, stdin io.Reader) (stdout, stderr []byte, err error) {
237 return nil, []byte("command not found\n"), errors.New("command not found")
239 return []byte(resp.stdout), []byte(resp.stderr), resp.err