Skip to content

Commit f56eb56

Browse files
authored
Cloud Tasks samples. (#516)
1 parent cafd46b commit f56eb56

File tree

11 files changed

+753
-0
lines changed

11 files changed

+753
-0
lines changed

appengine/cloudtasks/README.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Node.js Google Cloud Tasks sample for Google App Engine
2+
3+
This sample demonstrates how to use [Google Cloud Tasks](https://cloud.google.com/cloud-tasks/)
4+
on [Google App Engine Flexible Environment](https://cloud.google.com/appengine/docs/flexible/nodejs).
5+
6+
App Engine queues push tasks to an App Engine HTTP target. This directory
7+
contains both the App Engine app to deploy, as well as the snippets to run
8+
locally to push tasks to it, which could also be called on App Engine.
9+
10+
`createTask.js` is a simple command-line program to create tasks to be pushed to
11+
the App Engine app.
12+
13+
`server.js` is the main App Engine app. This app serves as an endpoint to
14+
receive App Engine task attempts.
15+
16+
`app.yaml` configures the App Engine app.
17+
18+
* [Setup](#setup)
19+
* [Running locally](#running-locally)
20+
* [Deploying to App Engine](#deploying-to-app-engine)
21+
* [Running the tests](#running-the-tests)
22+
23+
## Setup
24+
25+
Before you can run or deploy the sample, you need to do the following:
26+
27+
1. Refer to the [appengine/README.md][readme] file for instructions on
28+
running and deploying.
29+
1. Enable the Cloud Tasks API in the [Google Cloud Console](https://cloud.google.com/apis/library/cloudtasks.googleapis.com).
30+
1. Install dependencies:
31+
32+
With `npm`:
33+
34+
npm install
35+
36+
or with `yarn`:
37+
38+
yarn install
39+
40+
## Creating a queue
41+
42+
To create a queue using the Cloud SDK, use the following gcloud command:
43+
44+
gcloud alpha tasks queues create-app-engine-queue my-appengine-queue
45+
46+
Note: A newly created queue will route to the default App Engine service and
47+
version unless configured to do otherwise. Read the online help for the
48+
`create-app-engine-queue` or the `update-app-engine-queue` commands to learn
49+
about routing overrides for App Engine queues.
50+
51+
## Deploying the App Engine app
52+
53+
Deploy the App Engine app with gcloud:
54+
55+
gcloud app deploy
56+
57+
Verify the index page is serving:
58+
59+
gcloud app browse
60+
61+
The App Engine app serves as a target for the push requests. It has an
62+
endpoint `/log_payload` that reads the payload (i.e., the request body) of the
63+
HTTP POST request and logs it. The log output can be viewed with:
64+
65+
gcloud app logs read
66+
67+
## Running the Samples
68+
69+
To get usage information: `node createTask.js --help`
70+
71+
Which prints:
72+
73+
```
74+
Options:
75+
--version Show version number [boolean]
76+
--location, -l Location of the queue to add the task to. [string] [required]
77+
--queue, -q ID (short name) of the queue to add the task to. [string] [required]
78+
--project, -p Project of the queue to add the task to. [string] [required]
79+
--payload, -d (Optional) Payload to attach to the push queue. [string]
80+
--inSeconds, -s (Optional) The number of seconds from now to schedule task attempt. [number]
81+
--help Show help [boolean]
82+
83+
Examples:
84+
node createTask.js --project my-project-id
85+
86+
For more information, see https://cloud.google.com/cloud-tasks
87+
```

appengine/cloudtasks/app.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
env: flex
2+
runtime: nodejs

appengine/cloudtasks/createTask.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**
2+
* Copyright 2017, Google, Inc.
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+
* http://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+
16+
'use strict';
17+
18+
const google = require('googleapis');
19+
const cloudtasks = google.cloudtasks('v2beta2');
20+
21+
function authorize (callback) {
22+
google.auth.getApplicationDefault(function (err, authClient) {
23+
if (err) {
24+
console.error('authentication failed: ', err);
25+
return;
26+
}
27+
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
28+
var scopes = ['https://www.googleapis.com/auth/cloud-platform'];
29+
authClient = authClient.createScoped(scopes);
30+
}
31+
callback(authClient);
32+
});
33+
}
34+
35+
/**
36+
* Create a task for a given queue with an arbitrary payload.
37+
*/
38+
function createTask (project, location, queue, options) {
39+
authorize((authClient) => {
40+
const task = {
41+
app_engine_http_request: {
42+
http_method: 'POST',
43+
relative_url: '/log_payload'
44+
}
45+
};
46+
47+
if (options.payload !== undefined) {
48+
task.app_engine_http_request.payload = Buffer.from(options.payload).toString('base64');
49+
}
50+
51+
if (options.inSeconds !== undefined) {
52+
task.schedule_time = (new Date(options.inSeconds * 1000 + Date.now())).toISOString();
53+
}
54+
55+
const request = {
56+
parent: `projects/${project}/locations/${location}/queues/${queue}`, // TODO: Update placeholder value.
57+
resource: {
58+
task: task
59+
},
60+
auth: authClient
61+
};
62+
63+
console.log('Sending task %j', task);
64+
65+
cloudtasks.projects.locations.queues.tasks.create(request, (err, response) => {
66+
if (err) {
67+
console.error(err);
68+
return;
69+
}
70+
71+
console.log('Created task.', response.name);
72+
console.log(JSON.stringify(response, null, 2));
73+
});
74+
});
75+
}
76+
77+
const cli = require(`yargs`)
78+
.options({
79+
location: {
80+
alias: 'l',
81+
description: 'Location of the queue to add the task to.',
82+
type: 'string',
83+
requiresArg: true,
84+
required: true
85+
},
86+
queue: {
87+
alias: 'q',
88+
description: 'ID (short name) of the queue to add the task to.',
89+
type: 'string',
90+
requiresArg: true,
91+
required: true
92+
},
93+
project: {
94+
alias: 'p',
95+
description: 'Project of the queue to add the task to.',
96+
default: process.env.GCLOUD_PROJECT,
97+
type: 'string',
98+
requiresArg: true,
99+
required: true
100+
},
101+
payload: {
102+
alias: 'd',
103+
description: '(Optional) Payload to attach to the push queue.',
104+
type: 'string',
105+
requiresArg: true
106+
},
107+
inSeconds: {
108+
alias: 's',
109+
description: '(Optional) The number of seconds from now to schedule task attempt.',
110+
type: 'number',
111+
requiresArg: true
112+
}
113+
})
114+
.example(`node $0 --project my-project-id`)
115+
.wrap(120)
116+
.recommendCommands()
117+
.epilogue(`For more information, see https://cloud.google.com/cloud-tasks`)
118+
.strict();
119+
120+
if (module === require.main) {
121+
const opts = cli.help().parse(process.argv.slice(2));
122+
123+
process.env.GCLOUD_PROJECT = opts.project;
124+
125+
createTask(opts.project, opts.location, opts.queue, opts);
126+
}
127+
128+
exports.authorize = authorize;
129+
exports.createTask = createTask;

appengine/cloudtasks/package.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "appengine-cloudtasks",
3+
"description": "Google App Engine Flexible Environment Cloud Tasks example.",
4+
"version": "0.0.0",
5+
"license": "Apache-2.0",
6+
"author": "Google Inc.",
7+
"private": true,
8+
"repository": "GoogleCloudPlatform/nodejs-docs-samples",
9+
"engines": {
10+
"node": ">=4.0.0"
11+
},
12+
"scripts": {
13+
"deploy": "gcloud app deploy",
14+
"lint": "repo-tools lint",
15+
"pretest": "npm run lint",
16+
"unit-test": "ava --verbose test/*.test.js",
17+
"system-test": "repo-tools test app --config package.json --config-key cloud-repo-tools",
18+
"all-test": "npm run unit-test && npm run system-test",
19+
"test": "repo-tools test run --cmd npm -- run all-test",
20+
"e2e-test": "repo-tools test deploy --config package.json --config-key cloud-repo-tools"
21+
},
22+
"dependencies": {
23+
"body-parser": "1.18.2",
24+
"express": "4.16.2",
25+
"googleapis": "22.2.0",
26+
"yargs": "10.0.3"
27+
},
28+
"devDependencies": {
29+
"@google-cloud/nodejs-repo-tools": "2.1.1",
30+
"proxyquire": "1.8.0",
31+
"sinon": "4.0.2"
32+
},
33+
"cloud-repo-tools": {
34+
"requiresKeyFile": true,
35+
"requiresProjectId": true,
36+
"test": {
37+
"app": {
38+
"msg": "Hello, world!",
39+
"args": [
40+
"server.js"
41+
]
42+
}
43+
}
44+
}
45+
}

appengine/cloudtasks/server.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright 2017, Google, Inc.
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+
* http://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+
16+
'use strict';
17+
18+
const bodyParser = require('body-parser');
19+
const express = require('express');
20+
21+
const app = express();
22+
app.enable('trust proxy');
23+
24+
app.use(bodyParser.raw());
25+
app.use(bodyParser.json());
26+
app.use(bodyParser.text());
27+
28+
app.get('/', (req, res, next) => {
29+
// Basic index to verify app is serving
30+
res.send('Hello, world!').end();
31+
});
32+
33+
app.post('/log_payload', (req, res, next) => {
34+
// Log the request payload
35+
console.log('Received task with payload: %s', req.body);
36+
res.send(`Printed task payload: ${req.body}`).end();
37+
});
38+
39+
app.get('*', (req, res) => {
40+
res.send('OK').end();
41+
});
42+
43+
const PORT = process.env.PORT || 8080;
44+
app.listen(process.env.PORT || 8080, () => {
45+
console.log(`App listening on port ${PORT}`);
46+
console.log('Press Ctrl+C to quit.');
47+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Copyright 2017, Google, Inc.
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+
* http://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+
16+
'use strict';
17+
18+
const proxyquire = require(`proxyquire`).noCallThru();
19+
const sinon = require(`sinon`);
20+
const test = require(`ava`);
21+
const tools = require(`@google-cloud/nodejs-repo-tools`);
22+
23+
test.before(tools.stubConsole);
24+
test.after.always(tools.restoreConsole);
25+
26+
test.cb(`should create a task`, (t) => {
27+
const responseMock = {
28+
name: 'foo'
29+
};
30+
const cloudtasksMock = {
31+
projects: {
32+
locations: {
33+
queues: {
34+
tasks: {
35+
create: sinon.stub().yields(responseMock)
36+
}
37+
}
38+
}
39+
}
40+
};
41+
const authClientMock = {};
42+
43+
const util = proxyquire(`../createTask`, {
44+
googleapis: {
45+
cloudtasks: sinon.stub().returns(cloudtasksMock),
46+
auth: {
47+
getApplicationDefault: sinon.stub().yields(null, authClientMock)
48+
}
49+
}
50+
});
51+
52+
util.createTask('p', 'l', 'q', {});
53+
54+
setTimeout(() => {
55+
t.true(console.log.called);
56+
t.is(cloudtasksMock.projects.locations.queues.tasks.create.callCount, 1);
57+
t.end();
58+
}, 500);
59+
});

circle.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ deployment:
8888
- node scripts/build "auth"
8989
- node scripts/build "appengine/pubsub"
9090
- node scripts/build "bigquery"
91+
- export GCP_QUEUE=nodejs-test-queue-do-not-delete; node scripts/build "cloudtasks"
9192
- node scripts/build "containerengine/hello-world"
9293
- node scripts/build "datastore"
9394
- node scripts/build "debugger"

0 commit comments

Comments
 (0)