diff --git a/.jshintignore b/.jshintignore index 6dda6f89bf9..c72813792cf 100644 --- a/.jshintignore +++ b/.jshintignore @@ -6,5 +6,6 @@ appengine/sails/tasks/** appengine/sails/assets/** appengine/sails/api/responses/** appengine/webpack/dist/** +functions/** **/node_modules/** coverage/ \ No newline at end of file diff --git a/README.md b/README.md index eee8e07bf82..9e85448c138 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This repository holds Node.js samples used throughout [cloud.google.com](). ## Table of Contents * [Google App Engine](#google-app-engine) +* [Google Cloud Functions](#google-cloud-functions) * [Google Cloud Logging](#google-cloud-logging) * [Google Cloud Pub/Sub](#google-cloud-pubsub) * [Google Cloud Storage](#google-cloud-storage) @@ -67,10 +68,14 @@ __Other Examples__ - Reading/writing from/to disk - [Source code][aedisk_1] - Serving static files - [Source code][aestaticfiles_1] -## Google Cloud Datastorem +## Google Cloud Datastore - Tasks sample - [Source code][datastore_1] | [Documentation][datastore_2] +## Google Cloud Functions + +- Samples - [Source code][functions_1] | [Documentation][functions_2] + ## Google Cloud Logging - Reading logs sample - [Source code][logging_read_1] | [Documentation][logging_read_2] @@ -251,6 +256,9 @@ See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/ma [datastore_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/datastore/tasks.js [datastore_2]: https://cloud.google.com/datastore/docs/concepts/overview +[functions_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/functions/ +[functions_2]: https://cloud.google.com/functions/docs + [logging_read_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/logging/list.js [logging_read_2]: https://cloud.google.com/logging/docs/api/tasks/authorization [logging_write_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/logging/write.js diff --git a/functions/helloworld/README.md b/functions/helloworld/README.md new file mode 100644 index 00000000000..359bd7e40e2 --- /dev/null +++ b/functions/helloworld/README.md @@ -0,0 +1,19 @@ +# Google Cloud Functions Hello World! sample + +This sample shows a single exported function–a basic hello world example. + +## Deploy sample + +This example deploys the function with an HTTP trigger. + +``` +gcloud alpha functions deploy helloworld --bucket --trigger-http +``` + +## Test the function + +``` +gcloud alpha functions call helloworld +``` + +Running the above command should print "Hello World!". diff --git a/functions/helloworld/index.js b/functions/helloworld/index.js new file mode 100644 index 00000000000..66ae47f49fb --- /dev/null +++ b/functions/helloworld/index.js @@ -0,0 +1,20 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START helloworld] +exports.helloworld = function (context, data) { + context.success('Hello World!'); +}; +// [END helloworld] diff --git a/functions/log/README.md b/functions/log/README.md new file mode 100644 index 00000000000..ff857a68859 --- /dev/null +++ b/functions/log/README.md @@ -0,0 +1,17 @@ +# Google Cloud Functions message sample + +This sample shows writing to logs in a Cloud Function. + +## Deploy sample + +This example deploys the function with an HTTP trigger. + +``` +gcloud alpha functions deploy helloworld --bucket --trigger-http +``` + +## Test the function + +``` +gcloud alpha functions call helloworld +``` diff --git a/functions/log/index.js b/functions/log/index.js new file mode 100644 index 00000000000..2beefc816d0 --- /dev/null +++ b/functions/log/index.js @@ -0,0 +1,35 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START log] +exports.helloworld = function (context, data) { + console.log('I am a log entry!'); + context.success(); +}; +// [END log] + +// [START walkthrough_pubsub] +exports.hellotopic = function (context, data) { + console.log('My GCF Function: ' + data.message); + context.success(); +}; +// [END walkthrough_pubsub] + +// [START walkthrough_http] +exports.hellohttp = function (context, data) { + // Use the success argument to send data back to the caller + context.success('My GCF Function: ' + data.message); +}; +// [END walkthrough_http] diff --git a/functions/message/README.md b/functions/message/README.md new file mode 100644 index 00000000000..dc8551534f0 --- /dev/null +++ b/functions/message/README.md @@ -0,0 +1,17 @@ +# Google Cloud Functions message sample + +This sample shows calling the `success` and `failure` callbacks. + +## Deploy sample + +This example deploys the function with an HTTP trigger. + +``` +gcloud alpha functions deploy helloworld --bucket --trigger-http +``` + +## Test the function + +``` +gcloud alpha functions call helloworld +``` diff --git a/functions/message/index.js b/functions/message/index.js new file mode 100644 index 00000000000..defd9ab5772 --- /dev/null +++ b/functions/message/index.js @@ -0,0 +1,29 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START message] +module.exports = { + helloworld: function (context, data) { + if (data.message !== undefined) { + // Everything is ok + console.log(data.message); + context.success(); + } else { + // This is an error case + context.failure('No message defined!'); + } + } +}; +// [END message] diff --git a/functions/module/README.md b/functions/module/README.md new file mode 100644 index 00000000000..25e55080107 --- /dev/null +++ b/functions/module/README.md @@ -0,0 +1,20 @@ +# Google Cloud Functions module sample + +This sample shows exporting a Google Cloud Function as part of a module, which +is the method one would use to store multiple function in a single source file. + +## Deploy sample + +This example deploys the function with an HTTP trigger. + +``` +gcloud alpha functions deploy helloworld --bucket --trigger-http +``` + +## Test the function + +``` +gcloud alpha functions call helloworld +``` + +Running the above command should print a generated UUID. diff --git a/functions/module/index.js b/functions/module/index.js new file mode 100644 index 00000000000..c8204c953b5 --- /dev/null +++ b/functions/module/index.js @@ -0,0 +1,22 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START module] +module.exports = { + helloworld: function (context, data) { + context.success('Hello World!'); + } +}; +// [END module] diff --git a/functions/uuid/README.md b/functions/uuid/README.md new file mode 100644 index 00000000000..d076b8c0105 --- /dev/null +++ b/functions/uuid/README.md @@ -0,0 +1,20 @@ +# Google Cloud Functions UUID sample + +This sample shows a Google Cloud Function that uses a dependency from NPM, and +is a handy way to generate a v4 UUID from the command-line. + +## Deploy sample + +This example deploys the function with an HTTP trigger. + +``` +gcloud alpha functions deploy uuid --bucket --trigger-http +``` + +## Test the function + +``` +gcloud alpha functions call uuid +``` + +Running the above command should print a generated UUID. diff --git a/functions/uuid/index.js b/functions/uuid/index.js new file mode 100644 index 00000000000..a1987443a9d --- /dev/null +++ b/functions/uuid/index.js @@ -0,0 +1,22 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START uuid] +var uuid = require('node-uuid'); + +exports.uuid = function (context, data) { + context.success(uuid.v4()); +}; +// [END uuid] diff --git a/functions/uuid/package.json b/functions/uuid/package.json new file mode 100644 index 00000000000..bc9a382a04d --- /dev/null +++ b/functions/uuid/package.json @@ -0,0 +1,21 @@ +{ + "name": "nodejs-docs-samples-functions", + "description": "Node.js samples found on https://cloud.google.com", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "contributors": [ + { + "name": "Jason Dobry", + "email": "jason.dobry@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" + }, + "dependencies": { + "node-uuid": "^1.4.7" + } +} diff --git a/package.json b/package.json index 37354831de5..dc873c15432 100644 --- a/package.json +++ b/package.json @@ -28,14 +28,15 @@ "mocha": "mocha --timeout 10000 --recursive", "cover": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- -t 30000 --recursive", "coveralls": "cat ./coverage/lcov.info | node_modules/.bin/coveralls", - "deps_datastore": "cd datastore; npm i; cd ../..", - "deps_pubsub": "cd pubsub; npm i; cd ../..", - "deps_storage": "cd storage; npm i; cd ../..", - "deps_prediction": "cd prediction; npm i; cd ../..", - "deps_logging": "cd logging; npm i; cd ../..", + "deps_datastore": "cd datastore; npm i; cd ../", + "deps_pubsub": "cd pubsub; npm i; cd ../", + "deps_storage": "cd storage; npm i; cd ../", + "deps_prediction": "cd prediction; npm i; cd ../", + "deps_logging": "cd logging; npm i; cd ../", + "deps_functions": "cd functions/uuid; npm i; cd ../..", "deps_sendgrid": "cd computeengine/sendgrid; npm i; cd ../..", "pretest_geddy": "cd appengine/geddy; npm i geddy; GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && node node_modules/.bin/geddy gen secret; cd ../..;", - "pretest": "npm run deps_datastore; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_sendgrid; npm run pretest_geddy", + "pretest": "npm run deps_datastore; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_sendgrid; npm run pretest_geddy", "test": "npm run jshint && npm run cover" }, "devDependencies": { diff --git a/test/functions/helloworld.test.js b/test/functions/helloworld.test.js new file mode 100644 index 00000000000..0482d0f3dae --- /dev/null +++ b/test/functions/helloworld.test.js @@ -0,0 +1,33 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var assert = require('assert'); + +var helloworldSample = require('../../functions/helloworld'); + +describe('functions/helloworld', function () { + it('should return a hello world message', function (done) { + helloworldSample.helloworld({ + success: function (result) { + try { + assert.equal(result, 'Hello World!'); + done(); + } catch (err) { + done(err); + } + } + }); + }); +}); diff --git a/test/functions/log.test.js b/test/functions/log.test.js new file mode 100644 index 00000000000..8aac3123ee6 --- /dev/null +++ b/test/functions/log.test.js @@ -0,0 +1,98 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var assert = require('assert'); + +var logSample = require('../../functions/log'); + +describe('functions/log', function () { + it('should write to log', function (done) { + var logMessage = 'I am a log entry!'; + var messageWasPrinted = false; + var originalLog = console.log; + + console.log = function (data) { + if (data === logMessage) { + messageWasPrinted = true; + } + }; + + logSample.helloworld({ + success: function (result) { + try { + assert.equal(result, undefined); + if (messageWasPrinted) { + console.log = originalLog; + done(); + } else { + console.log = originalLog; + done('message was not printed!'); + } + } catch (err) { + console.log = originalLog; + done(err); + } + } + }); + }); + it('should write to log 2', function (done) { + var logMessage = 'My GCF Function: foo'; + var messageWasPrinted = false; + var originalLog = console.log; + + console.log = function (data) { + if (data === logMessage) { + messageWasPrinted = true; + } + }; + + logSample.hellotopic({ + success: function (result) { + try { + assert.equal(result, undefined); + if (messageWasPrinted) { + console.log = originalLog; + done(); + } else { + console.log = originalLog; + done('message was not printed!'); + } + } catch (err) { + console.log = originalLog; + done(err); + } + } + }, + { + message: 'foo' + }); + }); + it('should write to log 3', function (done) { + var logMessage = 'My GCF Function: foo'; + logSample.hellohttp({ + success: function (result) { + try { + assert.equal(result, logMessage); + done(); + } catch (err) { + done(err); + } + } + }, + { + message: 'foo' + }); + }); +}); diff --git a/test/functions/message.test.js b/test/functions/message.test.js new file mode 100644 index 00000000000..667fde0918d --- /dev/null +++ b/test/functions/message.test.js @@ -0,0 +1,64 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var assert = require('assert'); + +var messageSample = require('../../functions/message'); + +describe('functions/message', function () { + it('should print a message', function (done) { + var testMessage = 'test message'; + var messageWasPrinted = false; + var originalLog = console.log; + + console.log = function (data) { + if (data === testMessage) { + messageWasPrinted = true; + } + }; + + messageSample.helloworld({ + success: function (result) { + try { + assert.equal(result, undefined); + if (messageWasPrinted) { + console.log = originalLog; + done(); + } else { + console.log = originalLog; + done('message was not printed!'); + } + } catch (err) { + console.log = originalLog; + done(err); + } + } + }, { + message: testMessage + }); + }); + it('should say no message was providied', function (done) { + messageSample.helloworld({ + failure: function (result) { + try { + assert.equal(result, 'No message defined!'); + done(); + } catch (err) { + done(err); + } + } + }, {}); + }); +}); diff --git a/test/functions/module.test.js b/test/functions/module.test.js new file mode 100644 index 00000000000..95b17006f8d --- /dev/null +++ b/test/functions/module.test.js @@ -0,0 +1,33 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var assert = require('assert'); + +var moduleSample = require('../../functions/module'); + +describe('functions/module', function () { + it('should return a hello world message', function (done) { + moduleSample.helloworld({ + success: function (result) { + try { + assert.equal(result, 'Hello World!'); + done(); + } catch (err) { + done(err); + } + } + }); + }); +}); diff --git a/test/functions/uuid.test.js b/test/functions/uuid.test.js new file mode 100644 index 00000000000..ea4c9c1e56f --- /dev/null +++ b/test/functions/uuid.test.js @@ -0,0 +1,34 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var assert = require('assert'); + +var uuidSample = require('../../functions/uuid'); + +describe('functions/uuid', function () { + it('should generate a uuid', function (done) { + uuidSample.uuid({ + success: function (uuid) { + try { + assert.equal(typeof uuid, 'string'); + assert.equal(uuid.length, 36); + done(); + } catch (err) { + done(err); + } + } + }); + }); +}); diff --git a/test/pubsub/subscription.test.js b/test/pubsub/subscription.test.js index 317a1a87ff5..28b03c0a960 100644 --- a/test/pubsub/subscription.test.js +++ b/test/pubsub/subscription.test.js @@ -36,7 +36,14 @@ describe('pubsub/subscription', function () { // apiResponse assert.ok(responses[1][1]); // topics - assert.equal(responses[2][0][0].name, expectedTopic); + var foundExpectedTopic = false; + responses[2][0].forEach(function (topic) { + if (topic.name === expectedTopic) { + foundExpectedTopic = true; + return false; + } + }); + assert.ok(foundExpectedTopic, 'topic should have been created!'); assert.ok(responses[2][0][0].iam); // subscriptions assert.ok(responses[3][0][0].on);