Skip to content

Commit 7c6e9d9

Browse files
averikitschTakashi Matsuosofisl
authored
chore: add E2E tests for Jobs (GoogleCloudPlatform#2532)
* chore: add E2E tests for Jobs * lint * add project * debug * debug * Debug * fix command * Update command flag Co-authored-by: Takashi Matsuo <tmatsuo@google.com> Co-authored-by: sofisl <55454395+sofisl@users.noreply.github.com>
1 parent d689fe5 commit 7c6e9d9

8 files changed

Lines changed: 228 additions & 7 deletions

File tree

run/jobs/.gcloudignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
test/
21
README.md
32
node_modules/

run/jobs/README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Cloud Run Sample
1+
# Cloud Run Jobs Sample
22

33
## Build
44

@@ -29,6 +29,18 @@ docker run --rm -e FAIL_RATE=0.9 -e SLEEP_MS=1000 gcr.io/${GOOGLE_CLOUD_PROJECT}
2929
npm test
3030
```
3131

32-
## Deploy
32+
## Create a Job
3333

34-
~coming soon~
34+
```
35+
gcloud alpha run jobs create job-quickstart \
36+
--image=gcr.io/$PROJECT_ID/logger-job \
37+
--tasks 50 \
38+
--set-env-vars=SLEEP_MS=10000 \
39+
--set-env-vars=FAIL_RATE=0.5 \
40+
--max-retries 10
41+
```
42+
43+
## Run the Job
44+
```
45+
gcloud alpha run jobs run job-quickstart
46+
```

run/jobs/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
// limitations under the License.
1414

1515
'use strict';
16-
16+
// [START cloudrun_jobs_env_vars]
1717
// Retrieve Job-defined env vars
1818
const {TASK_NUM = 0, ATTEMPT_NUM = 0} = process.env;
1919
// Retrieve User-defined env vars
2020
const {SLEEP_MS, FAIL_RATE} = process.env;
21+
// [END cloudrun_jobs_env_vars]
2122

2223
// Define main script
2324
const main = async () => {
@@ -62,5 +63,7 @@ const randomFailure = rate => {
6263
// Start script
6364
main().catch(err => {
6465
console.error(err);
66+
// [START cloudrun_jobs_exit_process]
6567
process.exit(1); // Retry Job Task by exiting the process
68+
// [END cloudrun_jobs_exit_process]
6669
});

run/jobs/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"main": "index.js",
66
"scripts": {
77
"start": "node index.js",
8-
"test": "mocha test/index.test.js --exit"
8+
"test": "mocha test/index.test.js --exit",
9+
"system-test": "mocha test/system.test.js --timeout=600000 --exit"
910
},
1011
"author": "Google LLC",
1112
"license": "Apache-2.0",
1213
"devDependencies": {
13-
"mocha": "^9.1.3"
14+
"@google-cloud/logging": "^9.6.8",
15+
"mocha": "^9.2.0"
1416
}
1517
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
steps:
2+
3+
- id: 'Delete image and service'
4+
name: 'gcr.io/cloud-builders/gcloud'
5+
entrypoint: '/bin/bash'
6+
args:
7+
- '-c'
8+
- |
9+
./test/retry.sh "gcloud container images describe gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION}" \
10+
"gcloud container images delete gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION} --quiet"
11+
12+
./test/retry.sh "gcloud alpha run jobs describe ${_SERVICE} --project ${PROJECT_ID} --region ${_REGION}" \
13+
"gcloud alpha run jobs delete ${_SERVICE} --project ${PROJECT_ID} --region ${_REGION} --quiet"
14+
15+
substitutions:
16+
_SERVICE: logger-job
17+
_VERSION: manual
18+
_REGION: us-central1
19+

run/jobs/test/e2e_test_setup.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
steps:
2+
3+
- id: 'Build Container Image'
4+
name: 'gcr.io/cloud-builders/gcloud:latest'
5+
entrypoint: /bin/bash
6+
args:
7+
- '-c'
8+
- |
9+
./test/retry.sh "gcloud builds submit \
10+
--pack image=gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION}"
11+
12+
- id: 'Deploy to Cloud Run'
13+
name: 'gcr.io/cloud-builders/gcloud:latest'
14+
entrypoint: /bin/bash
15+
args:
16+
- '-c'
17+
- |
18+
gcloud components update --quiet
19+
20+
./test/retry.sh "gcloud alpha run jobs create ${_SERVICE} \
21+
--image gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION} \
22+
--project ${PROJECT_ID} \
23+
--region ${_REGION} \
24+
--tasks 2 \
25+
--set-env-vars=SLEEP_MS=100 \
26+
--max-retries 0 \
27+
--wait"
28+
29+
substitutions:
30+
_SERVICE: logger-job
31+
_VERSION: manual
32+
_REGION: us-central1

run/jobs/test/retry.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2020 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
##
17+
# retry.sh
18+
# Provides utility function commonly needed across Cloud Build pipelines to
19+
# retry commands on failure.
20+
#
21+
# Usage:
22+
# 1. Retry single command:
23+
#
24+
# ./retry.sh "CMD"
25+
#
26+
# 2. Retry with check:
27+
#
28+
# ./retry.sh "gcloud RESOURCE EXISTS?" "gcloud ACTION"
29+
#
30+
##
31+
32+
# Usage: try "cmd1" "cmd2"
33+
# If first cmd executes successfully then execute second cmd
34+
runIfSuccessful() {
35+
echo "running: $1"
36+
$($1 > /dev/null)
37+
if [ $? -eq 0 ]; then
38+
echo "running: $2"
39+
$($2 > /dev/null)
40+
fi
41+
}
42+
43+
# Define max retries
44+
max_attempts=3;
45+
attempt_num=1;
46+
47+
arg1="$1"
48+
arg2="$2"
49+
50+
if [ $# -eq 1 ]
51+
then
52+
cmd="$arg1"
53+
else
54+
cmd="runIfSuccessful \"$arg1\" \"$arg2\""
55+
fi
56+
57+
until eval $cmd
58+
do
59+
if ((attempt_num==max_attempts))
60+
then
61+
echo "Attempt $attempt_num / $max_attempts failed! No more retries left!"
62+
exit 1
63+
else
64+
echo "Attempt $attempt_num / $max_attempts failed!"
65+
sleep $((attempt_num++))
66+
fi
67+
done

run/jobs/test/system.test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
const assert = require('assert');
16+
const {execSync} = require('child_process');
17+
const {Logging} = require('@google-cloud/logging');
18+
19+
describe('End-to-End Tests', () => {
20+
const {GOOGLE_CLOUD_PROJECT} = process.env;
21+
if (!GOOGLE_CLOUD_PROJECT) {
22+
throw Error('"GOOGLE_CLOUD_PROJECT" env var not found.');
23+
}
24+
let {SERVICE_NAME} = process.env;
25+
if (!SERVICE_NAME) {
26+
SERVICE_NAME = 'logger-job';
27+
console.log(
28+
`"SERVICE_NAME" env var not found. Defaulting to "${SERVICE_NAME}"`
29+
);
30+
}
31+
const {SAMPLE_VERSION} = process.env;
32+
const REGION = 'us-central1';
33+
before(async () => {
34+
// Deploy service using Cloud Build
35+
let buildCmd =
36+
`gcloud builds submit --project ${GOOGLE_CLOUD_PROJECT} ` +
37+
'--config ./test/e2e_test_setup.yaml ' +
38+
`--substitutions _SERVICE=${SERVICE_NAME},_REGION=${REGION}`;
39+
if (SAMPLE_VERSION) buildCmd += `,_VERSION=${SAMPLE_VERSION}`;
40+
41+
console.log('Starting Cloud Build...');
42+
execSync(buildCmd);
43+
console.log('Cloud Build completed.');
44+
});
45+
46+
after(() => {
47+
let cleanUpCmd =
48+
`gcloud builds submit --project ${GOOGLE_CLOUD_PROJECT} ` +
49+
'--config ./test/e2e_test_cleanup.yaml ' +
50+
`--substitutions _SERVICE=${SERVICE_NAME},_REGION=${REGION}`;
51+
if (SAMPLE_VERSION) cleanUpCmd += `,_VERSION=${SAMPLE_VERSION}`;
52+
53+
execSync(cleanUpCmd);
54+
});
55+
56+
const dateMinutesAgo = (date, min_ago) => {
57+
date.setMinutes(date.getMinutes() - min_ago);
58+
return date.toISOString();
59+
};
60+
61+
it('generates logs in Cloud Logging', async () => {
62+
const logging = new Logging({
63+
projectId: process.env.GOOGLE_CLOUD_PROJECT,
64+
});
65+
66+
const preparedFilter =
67+
'resource.type = "cloud_run_revision" ' +
68+
`resource.labels.service_name = "${SERVICE_NAME}" ` +
69+
`resource.labels.location = "${REGION}" ` +
70+
`timestamp>="${dateMinutesAgo(new Date(), 5)}"`;
71+
72+
const entries = await logging.getEntries({
73+
filter: preparedFilter,
74+
autoPaginate: false,
75+
pageSize: 3,
76+
});
77+
78+
assert(entries[0]);
79+
assert(entries[0].length > 0);
80+
const found = entries[0].find(entry => {
81+
return typeof entry.data === 'string'
82+
? entry.data.includes('Task')
83+
: false;
84+
});
85+
assert(found);
86+
});
87+
});

0 commit comments

Comments
 (0)