Skip to content

Commit

Permalink
Refactor Cloud Functions samples.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdobry committed Nov 10, 2016
1 parent 2cf8055 commit 8cb8f04
Show file tree
Hide file tree
Showing 38 changed files with 2,072 additions and 2,242 deletions.
78 changes: 41 additions & 37 deletions functions/background/index.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,72 @@
// 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.
/**
* 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]
// [START functions_background_helloworld]
/**
* Background Cloud Function.
*
* @param {Object} context Cloud Function context.
* @param {Object} data Request data, provided by a trigger.
* @param {string} data.message Message, provided by the trigger.
* @param {object} event The Cloud Functions event.
* @param {object} event.data The event data.
* @param {function} The callback function.
*/
exports.helloWorld = function helloWorld (context, data) {
if (data.message === undefined) {
// This is an error case, "message" is required
context.failure('No message defined!');
exports.helloWorld = function helloWorld (event, callback) {
if (!event.data.myMessage) {
// This is an error case, "myMessage" is required
callback(new Error('No message defined!'));
} else {
// Everything is ok
console.log(data.message);
context.success();
console.log(event.data.myMessage);
callback();
}
};
// [END helloworld]

// [START helloPromise]
var request = require('request-promise');
// [END functions_background_helloworld]

// [START functions_background_promise]
/**
* Background Cloud Function that returns a Promise. Note that we don't pass
* a "context" argument to the function.
* a "callback" argument to the function.
*
* @param {Object} data Request data, provided by a trigger.
* @param {object} event The Cloud Functions event.
* @param {object} event.data The event data.
* @returns {Promise}
*/
exports.helloPromise = function helloPromise (data) {
exports.helloPromise = function helloPromise (event) {
const request = require('request-promise');

return request({
uri: data.endpoint
uri: event.data.endpoint
});
};
// [END helloPromise]
// [END functions_background_promise]

// [START helloSynchronous]
// [START functions_background_synchronous]
/**
* Background Cloud Function that returns synchronously. Note that we don't pass
* a "context" argument to the function.
* a "callback" argument to the function.
*
* @param {Object} data Request data, provided by a trigger.
* @param {object} event The Cloud Functions event.
* @param {object} event.data The event data.
*/
exports.helloSynchronous = function helloSynchronous (data) {
exports.helloSynchronous = function helloSynchronous (event) {
// This function returns synchronously
if (data.something === true) {
if (event.data.something === true) {
return 'Something is true!';
} else {
throw new Error('Something was not true!');
}
};
// [END helloSynchronous]
// [END functions_background_synchronous]
5 changes: 3 additions & 2 deletions functions/background/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"test": "mocha -R spec -t 120000 --require intelli-espower-loader ../../test/_setup.js test/*.test.js"
},
"dependencies": {
"request-promise": "^3.0.0"
"request": "^2.75.0",
"request-promise": "^4.1.1"
},
"devDependencies": {
"mocha": "^2.5.3"
"mocha": "^3.1.2"
}
}
133 changes: 68 additions & 65 deletions functions/background/test/index.test.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
// 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.
/**
* 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 proxyquire = require('proxyquire').noCallThru();
const proxyquire = require(`proxyquire`).noCallThru();

function getSample () {
var requestPromise = sinon.stub().returns(new Promise(function (resolve) {
resolve('test');
}));
const requestPromise = sinon.stub().returns(Promise.resolve(`test`));

return {
sample: proxyquire('../', {
program: proxyquire(`../`, {
'request-promise': requestPromise
}),
mocks: {
Expand All @@ -29,62 +30,64 @@ function getSample () {
};
}

function getMockContext () {
return {
success: sinon.stub(),
failure: sinon.stub()
};
}
describe(`functions:background`, () => {
it(`should echo message`, () => {
const event = {
data: {
myMessage: `hi`
}
};
const sample = getSample();
const callback = sinon.stub();

describe('functions:background', function () {
it('should echo message', function () {
var expectedMsg = 'hi';
var context = getMockContext();
var backgroundSample = getSample();
backgroundSample.sample.helloWorld(context, {
message: expectedMsg
});
sample.program.helloWorld(event, callback);

assert(context.success.calledOnce);
assert.equal(context.failure.called, false);
assert(console.log.calledWith(expectedMsg));
assert.equal(console.log.callCount, 1);
assert.deepEqual(console.log.firstCall.args, [event.data.myMessage]);
assert.equal(callback.callCount, 1);
assert.deepEqual(callback.firstCall.args, []);
});
it('should say no message was provided', function () {
var expectedMsg = 'No message defined!';
var context = getMockContext();
var backgroundSample = getSample();
backgroundSample.sample.helloWorld(context, {});

assert(context.failure.calledOnce);
assert(context.failure.firstCall.args[0] === expectedMsg);
assert.equal(context.success.called, false);
it(`should say no message was provided`, () => {
const error = new Error(`No message defined!`);
const callback = sinon.stub();
const sample = getSample();
sample.program.helloWorld({ data: {} }, callback);

assert.equal(callback.callCount, 1);
assert.deepEqual(callback.firstCall.args, [error]);
});
it('should make a promise request', function (done) {
var backgroundSample = getSample();
backgroundSample.sample.helloPromise({
endpoint: 'foo.com'
}).then(function (result) {
assert.deepEqual(backgroundSample.mocks.requestPromise.firstCall.args[0], {
uri: 'foo.com'

it(`should make a promise request`, () => {
const sample = getSample();
const event = {
data: {
endpoint: `foo.com`
}
};

return sample.program.helloPromise(event)
.then((result) => {
assert.deepEqual(sample.mocks.requestPromise.firstCall.args, [{ uri: `foo.com` }]);
assert.equal(result, `test`);
});
assert.equal(result, 'test');
done();
}, function () {
assert.fail();
});
});
it('should return synchronously', function () {
var backgroundSample = getSample();
assert(backgroundSample.sample.helloSynchronous({
something: true
}) === 'Something is true!');

it(`should return synchronously`, () => {
assert.equal(getSample().program.helloSynchronous({
data: {
something: true
}
}), `Something is true!`);
});
it('should throw an error', function () {
var backgroundSample = getSample();
assert.throws(function () {
backgroundSample.sample.helloSynchronous({
something: false

it(`should throw an error`, () => {
assert.throws(() => {
getSample().program.helloSynchronous({
data: {
something: false
}
});
}, Error, 'Something was not true!');
}, Error, `Something was not true!`);
});
});
70 changes: 50 additions & 20 deletions functions/datastore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

# Google Cloud Functions Cloud Datastore sample

This recipe shows you how to read and write an entity in Datastore from a Cloud Function.
This recipe shows you how to read and write an entity in Cloud Datastore from a
Cloud Function.

View the [source code][code].

Expand All @@ -20,46 +21,75 @@ Functions for your project.

1. Create a Cloud Storage Bucket to stage our deployment:

gsutil mb gs://[YOUR_BUCKET_NAME]
gsutil mb gs://YOUR_BUCKET_NAME

* Replace `[YOUR_BUCKET_NAME]` with the name of your Cloud Storage Bucket.
* Replace `YOUR_BUCKET_NAME` with the name of your Cloud Storage Bucket.

1. Ensure the Cloud Datastore API is enabled:

[Click here to enable the Cloud Datastore API](https://console.cloud.google.com/flows/enableapi?apiid=datastore.googleapis.com&redirect=https://github.com/GoogleCloudPlatform/nodejs-docs-samples/tree/master/functions/datastore)

1. Deploy the "ds-get" function with an HTTP trigger:
1. Deploy the "get" function with an HTTP trigger:

gcloud alpha functions deploy ds-get --bucket [YOUR_BUCKET_NAME] --trigger-http --entry-point get
gcloud alpha functions deploy get --stage-bucket YOUR_BUCKET_NAME --trigger-http

* Replace `[YOUR_BUCKET_NAME]` with the name of your Cloud Storage Bucket.
* Replace `YOUR_BUCKET_NAME` with the name of your Cloud Storage Bucket.

1. Deploy the "ds-set" function with an HTTP trigger:
1. Deploy the "set" function with an HTTP trigger:

gcloud alpha functions deploy ds-set --bucket [YOUR_BUCKET_NAME] --trigger-http --entry-point set
gcloud alpha functions deploy set --stage-bucket YOUR_BUCKET_NAME --trigger-http

* Replace `[YOUR_BUCKET_NAME]` with the name of your Cloud Storage Bucket.
* Replace `YOUR_BUCKET_NAME` with the name of your Cloud Storage Bucket.

1. Deploy the "ds-del" function with an HTTP trigger:
1. Deploy the "del" function with an HTTP trigger:

gcloud alpha functions deploy ds-del --bucket [YOUR_BUCKET_NAME] --trigger-http --entry-point del
gcloud alpha functions deploy del --stage-bucket YOUR_BUCKET_NAME --trigger-http

* Replace `[YOUR_BUCKET_NAME]` with the name of your Cloud Storage Bucket.
* Replace `YOUR_BUCKET_NAME` with the name of your Cloud Storage Bucket.

1. Call the "ds-set" function to create a new entity:
1. Call the "set" function to create a new entity:

gcloud alpha functions call ds-set --data '{"kind":"gcf-test","key":"foobar","value":{"message":"Hello World!"}}'
gcloud alpha functions call set --data '{"kind":"Task","key":"sampletask1","value":{"description":"Buy milk"}}'

1. Call the "ds-get" function to read the newly created entity:
or

gcloud alpha functions call ds-get --data '{"kind":"gcf-test","key":"foobar"}'
curl -H "Content-Type: application/json" -X POST -d '{"kind":"Task","key":"sampletask1","value":{"description":"Buy milk"}}' "https://[YOUR_REGION]-[YOUR_PROJECT_ID].cloudfunctions.net/set"

1. Call the "ds-del" function to delete the entity:
* Replace `[YOUR_REGION]` with the region where your function is deployed.
* Replace `[YOUR_PROJECT_ID]` with your Google Cloud Platform project ID.

gcloud alpha functions call ds-del --data '{"kind":"gcf-test","key":"foobar"}'
1. Call the "get" function to read the newly created entity:

1. Call the "ds-get" function again to verify it was deleted:
gcloud alpha functions call get --data '{"kind":"Task","key":"sampletask1"}'

or

curl -H "Content-Type: application/json" -X POST -d '{"kind":"Task","key":"sampletask1"}' "https://[YOUR_REGION]-[YOUR_PROJECT_ID].cloudfunctions.net/get"

* Replace `[YOUR_REGION]` with the region where your function is deployed.
* Replace `[YOUR_PROJECT_ID]` with your Google Cloud Platform project ID.

1. Call the "del" function to delete the entity:

gcloud alpha functions call del --data '{"kind":"Task","key":"sampletask1"}'

or

curl -H "Content-Type: application/json" -X POST -d '{"kind":"Task","key":"sampletask1"}' "https://[YOUR_REGION]-[YOUR_PROJECT_ID].cloudfunctions.net/del"

* Replace `[YOUR_REGION]` with the region where your function is deployed.
* Replace `[YOUR_PROJECT_ID]` with your Google Cloud Platform project ID.

1. Call the "get" function again to verify it was deleted:

gcloud alpha functions call get --data '{"kind":"Task","key":"sampletask1"}'

or

curl -H "Content-Type: application/json" -X POST -d '{"kind":"Task","key":"sampletask1"}' "https://[YOUR_REGION]-[YOUR_PROJECT_ID].cloudfunctions.net/get"

* Replace `[YOUR_REGION]` with the region where your function is deployed.
* Replace `[YOUR_PROJECT_ID]` with your Google Cloud Platform project ID.

gcloud alpha functions call ds-get --data '{"kind":"gcf-test","key":"foobar"}'

[quickstart]: https://cloud.google.com/functions/quickstart
Loading

0 comments on commit 8cb8f04

Please sign in to comment.