Skip to content
This repository was archived by the owner on Feb 27, 2020. It is now read-only.

Commit cd1dc4e

Browse files
authored
Merge pull request #373 from taskcluster/livelog-integration-test
Integration tests for livelog and fix for s3 upload
2 parents 21d46a6 + a8b8c6b commit cd1dc4e

19 files changed

+833
-558
lines changed

docker-tests.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ ARGS="$ARGS taskcluster/tc-worker-env";
1111

1212
TAGS='qemu network system native docker';
1313

14+
# ascii color escape sequences
15+
BOLD='\033[1m'
16+
RED='\033[0;31m'
17+
CLEAR='\033[0m'
18+
1419
if [[ "$@" == go\ * ]]; then
1520
docker run $ARGS "$@";
1621
elif [[ "$1" == -- ]]; then
@@ -26,8 +31,8 @@ else
2631
fi;
2732

2833
if [[ "$?" != "0" ]]; then
29-
echo "### TEST FAILED";
34+
echo -e "$RED$BOLD### TEST FAILED$CLEAR";
3035
exit 1;
3136
else
32-
echo "### TEST PASSED";
37+
echo -e "$BOLD### TEST PASSED$CLEAR";
3338
fi

engines/docker/engine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func TestArtifacts(t *testing.T) {
108108
"hello.txt",
109109
"sub-folder/hello2.txt",
110110
},
111-
NestedFolderPath: "/folder/",
111+
NestedFolderPath: "/folder",
112112
Payload: `{
113113
"command": ["sh", "-ec", "mkdir -p /folder/sub-folder; echo '[hello-world]' > /folder/hello.txt; echo '[hello-world]' > /folder/sub-folder/hello2.txt"],
114114
"image": {

engines/docker/resultset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (r *resultSet) ExtractFolder(path string, handler engines.FileHandler) erro
104104
if !strings.HasPrefix(name, "/") {
105105
name = "/" + name // Ensure we always have an absolute path
106106
}
107-
name = name[len(path):]
107+
name = name[len(path+"/"):]
108108
return handler(name, stream)
109109
})
110110
}

plugins/cache/cache_test.go

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestReadWriteEmptyCache(t *testing.T) {
3535
Engine: "mock",
3636
EngineConfig: `{}`,
3737
PluginConfig: testPluginConfig,
38-
Tasks: []workertest.Task{
38+
Tasks: workertest.Tasks([]workertest.Task{
3939
{
4040
Title: "Write hello-world to empty cache volume",
4141
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
@@ -56,8 +56,7 @@ func TestReadWriteEmptyCache(t *testing.T) {
5656
},
5757
AllowAdditional: true,
5858
Success: true,
59-
},
60-
{
59+
}, {
6160
Title: "Read from cache volume",
6261
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
6362
Payload: `{
@@ -78,7 +77,7 @@ func TestReadWriteEmptyCache(t *testing.T) {
7877
AllowAdditional: true,
7978
Success: true,
8079
},
81-
},
80+
}),
8281
}.TestWithFakeQueue(t) // TODO: Resolve scope issues and test against real queue
8382
}
8483

@@ -123,7 +122,7 @@ func TestReadPreloadCache(t *testing.T) {
123122
Engine: "mock",
124123
EngineConfig: `{}`,
125124
PluginConfig: testPluginConfig,
126-
Tasks: []workertest.Task{
125+
Tasks: workertest.Tasks([]workertest.Task{
127126
{
128127
Title: "Read from cache volume",
129128
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
@@ -145,8 +144,7 @@ func TestReadPreloadCache(t *testing.T) {
145144
},
146145
AllowAdditional: true,
147146
Success: true,
148-
},
149-
{
147+
}, {
150148
Title: "Read from cache volume again",
151149
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
152150
Payload: `{
@@ -167,8 +165,7 @@ func TestReadPreloadCache(t *testing.T) {
167165
},
168166
AllowAdditional: true,
169167
Success: true,
170-
},
171-
{
168+
}, {
172169
Title: "Write to preloaded cache volume",
173170
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
174171
Payload: `{
@@ -186,8 +183,7 @@ func TestReadPreloadCache(t *testing.T) {
186183
}`,
187184
AllowAdditional: true,
188185
Success: true,
189-
},
190-
{
186+
}, {
191187
Title: "Read from cache volume after write",
192188
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
193189
Payload: `{
@@ -208,8 +204,7 @@ func TestReadPreloadCache(t *testing.T) {
208204
},
209205
AllowAdditional: true,
210206
Success: true,
211-
},
212-
{
207+
}, {
213208
Title: "Read from read-only cache volume",
214209
Payload: `{
215210
"delay": 5,
@@ -228,8 +223,7 @@ func TestReadPreloadCache(t *testing.T) {
228223
},
229224
AllowAdditional: true,
230225
Success: true,
231-
},
232-
{
226+
}, {
233227
Title: "Read from read-only cache volume again",
234228
Payload: `{
235229
"delay": 5,
@@ -266,7 +260,7 @@ func TestReadPreloadCache(t *testing.T) {
266260
AllowAdditional: true,
267261
Success: false,
268262
},
269-
},
263+
}),
270264
}.TestWithFakeQueue(t) // TODO: Resolve scope issues and test against real queue
271265
}
272266

@@ -276,7 +270,7 @@ func TestCacheScopeRequired(t *testing.T) {
276270
Engine: "mock",
277271
EngineConfig: `{}`,
278272
PluginConfig: testPluginConfig,
279-
Tasks: []workertest.Task{
273+
Tasks: workertest.Tasks([]workertest.Task{
280274
{
281275
Title: "Write hello-world to empty cache volume",
282276
Scopes: []string{"worker:cache:dummy-garbage-wrong-cache-name"},
@@ -298,8 +292,7 @@ func TestCacheScopeRequired(t *testing.T) {
298292
AllowAdditional: true,
299293
Exception: runtime.ReasonMalformedPayload,
300294
Success: false,
301-
},
302-
{
295+
}, {
303296
Title: "Access with star-scope",
304297
Scopes: []string{"worker:cache:dummy-garbage-my-cache-*"},
305298
Payload: `{
@@ -317,7 +310,7 @@ func TestCacheScopeRequired(t *testing.T) {
317310
AllowAdditional: true,
318311
Success: true,
319312
},
320-
},
313+
}),
321314
}.TestWithFakeQueue(t) // TODO: Resolve scope issues and test against real queue
322315
}
323316

@@ -379,7 +372,7 @@ func TestPurgeCache(t *testing.T) {
379372
"purgeCacheBaseUrl": "` + s.URL + `"
380373
}
381374
}`,
382-
Tasks: []workertest.Task{
375+
Tasks: workertest.Tasks([]workertest.Task{
383376
{
384377
Title: "Write hello-world to empty cache volume",
385378
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
@@ -400,8 +393,7 @@ func TestPurgeCache(t *testing.T) {
400393
},
401394
AllowAdditional: true,
402395
Success: true,
403-
},
404-
{
396+
}, {
405397
Title: "Read from cache volume",
406398
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
407399
Payload: `{
@@ -421,8 +413,7 @@ func TestPurgeCache(t *testing.T) {
421413
},
422414
AllowAdditional: true,
423415
Success: true,
424-
},
425-
{
416+
}, {
426417
Title: "Ping purge-cache service to start purging",
427418
Payload: `{
428419
"delay": 5,
@@ -431,8 +422,7 @@ func TestPurgeCache(t *testing.T) {
431422
}`,
432423
AllowAdditional: true,
433424
Success: true,
434-
},
435-
{
425+
}, {
436426
Title: "Read from cache volume after purge",
437427
Scopes: []string{"worker:cache:dummy-garbage-my-cache-name"},
438428
Payload: `{
@@ -453,6 +443,6 @@ func TestPurgeCache(t *testing.T) {
453443
AllowAdditional: true,
454444
Success: false,
455445
},
456-
},
446+
}),
457447
}.TestWithFakeQueue(t) // TODO: Resolve scope issues and test against real queue
458448
}

runtime/artifact.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func (context *TaskContext) createArtifact(name string, req []byte) ([]byte, err
125125
}
126126

127127
func putArtifact(urlStr, mime string, stream ioext.ReadSeekCloser, additionalArtifacts map[string]string) error {
128+
defer stream.Close()
128129
u, err := url.Parse(urlStr)
129130
if err != nil {
130131
panic(errors.Wrap(err, "failed to parse URL"))
@@ -152,6 +153,13 @@ func putArtifact(urlStr, mime string, stream ioext.ReadSeekCloser, additionalArt
152153
if err != nil {
153154
return errors.Wrap(err, "Failed to seek start before uploading stream")
154155
}
156+
body := ioutil.NopCloser(stream)
157+
if contentLength == 0 {
158+
// Zero is the default value for ContentLength, so if we want to avoid
159+
// using transfer-encoding: chunked, not supported by S3, we have to
160+
// specify http.NoBody when content-length is zero
161+
body = http.NoBody
162+
}
155163
req := &http.Request{
156164
Method: "PUT",
157165
URL: u,
@@ -160,18 +168,19 @@ func putArtifact(urlStr, mime string, stream ioext.ReadSeekCloser, additionalArt
160168
ProtoMinor: 1,
161169
Header: header,
162170
ContentLength: contentLength,
163-
Body: stream,
171+
Body: body,
164172
GetBody: func() (io.ReadCloser, error) {
165173
// In case we have to follow any redirects, which shouldn't happen
166174
if _, serr := stream.Seek(0, io.SeekStart); serr != nil {
167175
return nil, errors.Wrap(serr, "failed to seek to start of stream")
168176
}
169-
return ioutil.NopCloser(stream), nil
177+
return body, nil
170178
},
171179
}
172180
resp, err := client.Do(req)
173181
if err != nil {
174182
if attempts < 10 {
183+
debug("attempting artifact upload again, due to error: %s", err)
175184
time.Sleep(backoff.Delay(attempts))
176185
continue
177186
}
@@ -188,6 +197,7 @@ func putArtifact(urlStr, mime string, stream ioext.ReadSeekCloser, additionalArt
188197
if resp.StatusCode/100 == 5 {
189198
// TODO: Make this configurable
190199
if attempts < 10 {
200+
debug("attempting artifact upload again, due to HTTP 5xx: %d", resp.StatusCode)
191201
time.Sleep(backoff.Delay(attempts))
192202
continue
193203
} else {

runtime/util/parallel.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package util
22

3-
import "sync"
3+
import (
4+
"errors"
5+
"sync"
6+
)
47

58
// Parallel takes a list of functions and calls them all in concurrently,
69
// returning when all the functions are done.
@@ -43,22 +46,29 @@ func Spawn(N int, fn func(i int)) {
4346
//
4447
// This utility is smart when instantiating elements in an array concurrently.
4548
func SpawnWithLimit(N, limit int, fn func(i int)) {
49+
if limit <= 0 {
50+
panic(errors.New("SpawnWithLimit called with limit <= 0"))
51+
}
4652
wg := sync.WaitGroup{}
4753
wg.Add(N)
4854
m := sync.Mutex{}
4955
c := sync.NewCond(&m)
5056
for index := 0; index < N; index++ {
57+
// Wait for limit to be non-zero
58+
m.Lock()
59+
for limit == 0 {
60+
c.Wait() // wait for signal
61+
}
62+
limit--
63+
m.Unlock()
64+
65+
// Spawn fn(i) for index
5166
go func(i int) {
5267
defer wg.Done()
53-
54-
m.Lock()
55-
defer m.Unlock()
56-
57-
for limit == 0 {
58-
c.Wait()
59-
}
60-
limit--
6168
defer func() {
69+
// Increment limit now that we're done and signal
70+
m.Lock()
71+
defer m.Unlock()
6272
limit++
6373
c.Signal()
6474
}()

tc-worker-env.Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ RUN echo '#!/bin/bash\n\
5555
dockerd -s vfs >/var/log/docker.log 2>&1 &\n\
5656
while [ ! -S /var/run/docker.sock ]; do sleep 0.1; done\n\
5757
"$@"\n\
58-
kill %1' > /usr/local/bin/with-dockerd.sh \
58+
RETVAL=$?\n\
59+
kill %1\n\
60+
exit "$RETVAL"' > /usr/local/bin/with-dockerd.sh \
5961
&& chmod +x /usr/local/bin/with-dockerd.sh
6062

6163
#trap "kill $!; wait $!" EXIT\n\

0 commit comments

Comments
 (0)