Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions #120

Merged
merged 7 commits into from
Jun 8, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions functions/datastore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there not a tutorial for this on devsite? Would it be more valuable to house most of this documentation there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be a more complete tutorial added to devsite.


# Google Cloud Functions Cloud Datastore sample

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

View the [source code][code].

[code]: index.js

## Deploy and Test

1. Follow the [Cloud Functions quickstart guide](https://cloud.google.com/functions/quickstart) to setup Cloud Functions for your project.

1. Clone this repository:

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
cd nodejs-docs-samples/functions/datastore

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

gsutil mb gs://<your-bucket-name>

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:

gcloud alpha functions deploy ds-get --bucket <your-bucket-name> --trigger-http --entry-point get

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

gcloud alpha functions deploy ds-set --bucket <your-bucket-name> --trigger-http --entry-point set

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

gcloud alpha functions deploy ds-del --bucket <your-bucket-name> --trigger-http --entry-point del

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

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

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

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

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

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

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

gcloud alpha functions call ds-get --data '{"kind": "gcf-test", "key": "foobar"}'
135 changes: 135 additions & 0 deletions functions/datastore/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// 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 gcloud = require('gcloud');

// Create a datastore client.
var datastore = gcloud.datastore();

// Gets a Datastore key from the kind/key pair in the request
function _getKeyFromData (data, callback) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is prefixing with an underscore the way to make things private in GCF?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requestData is a better variable name than data (literally everything is data).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is prefixing with an underscore the way to make things private in GCF?

No, it comes from the JavaScript convention of using underscores to signal that something should be considered private.

var key = data.key;
var kind = data.kind;

if (!key) {
return callback('Key not provided. Make sure you have a "key" property ' +
'in your request');
}

if (!kind) {
return callback('Kind not provided. Make sure you have a "kind" property ' +
'in your request');
}

return callback(null, datastore.key([kind, key]));
}

// Gets a Datastore entity based on the key information in the request and
// returns null if the entity does not exist
function _getEntity (data, callback) {
return _getKeyFromData(data, function (err, k) {
if (err) {
return callback(err);
}

return datastore.get(k, function (err, entity) {
if (err) {
return callback(err);
}
return callback(null, k, entity || null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is || null necessary? What does datastore return?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

});
});
}

// Saves (creates or inserts) an entity with the given key
function _saveEntity (key, entity, callback) {
return datastore.save({
key: key,
data: entity
}, callback);
}

/**

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use this style of comment here but // elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

* Creates and/or updates a record
*/
function set (context, data) {
// The value contains a JSON document representing the entity we want to save
var value = data.value;

if (!value) {
return context.failure('Value not provided. Make sure you have a "value" ' +
'property in your request');
}

_getKeyFromData(data, function (err, k) {
if (err) {
console.error(err);
return context.failure(err);
}

_saveEntity(k, value, function (err) {
if (err) {
console.error(err);
return context.failure(err);
}

return context.success('Entity saved');
});
});
}

/**
* Retrieves a record
*/
function get (context, data) {
return _getEntity(data, function (err, key, entity) {
if (err) {
console.error(err);
return context.failure(err);
}

// The get operation will not fail for a non-existent entity, it just returns null.
if (!entity) {
return context.failure('No entity found for key ' + key.path);
}

return context.success(entity);
});
}

/**
* Deletes a record
*/
function del (context, data) {
return _getKeyFromData(data, function (err, k) {
if (err) {
console.error(err);
return context.failure(err);
}

datastore.delete(k, function (err) {
if (err) {
console.error(err);
return context.failure(err);
}

return context.success('Entity deleted');
});
});
}

exports.set = set;
exports.get = get;
exports.del = del;
15 changes: 15 additions & 0 deletions functions/datastore/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "nodejs-docs-samples-functions-datastore",
"description": "Node.js samples found on https://cloud.google.com",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"repository": {
"type": "git",
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
},
"dependencies": {
"gcloud": "^0.35.0"
}
}
38 changes: 38 additions & 0 deletions functions/gcs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>

# Google Cloud Functions Cloud Storage sample

This recipe demonstrates how to load a file from Cloud Storage.

View the [source code][code].

[code]: index.js

## Deploy and Test

1. Follow the [Cloud Functions quickstart guide](https://cloud.google.com/functions/quickstart) to setup Cloud Functions for your project.

1. Clone this repository:

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
cd nodejs-docs-samples/functions/gcs

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

gsutil mb gs://<your-bucket-name>

1. Upload the sample file to the bucket:

gsutil cp sample.txt gs://<your-bucket-name>

1. Deploy the "wordCount" function with an HTTP trigger:

gcloud alpha functions deploy wordCount --bucket <your-bucket-name> --trigger-http --entry-point map

1. Call the "wordCount" function using the sample file:

gcloud alpha functions call wordCount --data '{"bucket": "<your-bucket-name>", "file": "sample.txt"}'

You should see something like this in your console

The file sample.txt has 114 words
52 changes: 52 additions & 0 deletions functions/gcs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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 gcloud = require('gcloud');
var readline = require('readline');

module.exports = {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense separate wordCount into a top-level function and then do exports.wordCount = wordCount? Or is it accepted style to do it this way for single-function modules?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

wordCount: function (context, data) {
var bucketName = data.bucket;
var fileName = data.file;

if (!bucketName) {
return context.failure('Bucket not provided. Make sure you have a ' +
'"bucket" property in your request');
}
if (!fileName) {
return context.failure('Filename not provided. Make sure you have a ' +
'"file" property in your request');
}

// Create a gcs client.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a similar question, does it make sense to separate the "Cloud Storage" parts from the "Cloud Function" parts like you did in the datastore sample?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

var gcs = gcloud.storage();
var bucket = gcs.bucket(bucketName);
var file = bucket.file(fileName);
var count = 0;

// Use the linebyline module to read the stream line by line.
var lineReader = readline.createInterface({
input: file.createReadStream()
});

lineReader.on('line', function (line) {
count += line.trim().split(/\s+/).length;
});

lineReader.on('close', function () {
context.success('The file ' + fileName + ' has ' + count + ' words');
});
}
};
15 changes: 15 additions & 0 deletions functions/gcs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "nodejs-docs-samples-functions-cloud-storage",
"description": "Node.js samples found on https://cloud.google.com",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"repository": {
"type": "git",
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
},
"dependencies": {
"gcloud": "^0.35.0"
}
}
14 changes: 14 additions & 0 deletions functions/gcs/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Shall I compare thee to a summer's day?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shakespeare is an interesting choice; I always go for Alice's Adventures in Wonderland. 😛

Thou art more lovely and more temperate:
Rough winds do shake the darling buds of May,
And summer's lease hath all too short a date:
Sometime too hot the eye of heaven shines,
And often is his gold complexion dimm'd;
And every fair from fair sometime declines,
By chance, or nature's changing course, untrimm'd;
But thy eternal summer shall not fade
Nor lose possession of that fair thou ow'st;
Nor shall Death brag thou wander'st in his shade,
When in eternal lines to time thou grow'st;
So long as men can breathe or eyes can see,
So long lives this, and this gives life to thee.
16 changes: 0 additions & 16 deletions functions/log/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,3 @@ exports.helloworld = function (context, data) {
context.success();
};
// [END log]

exports.log = exports.helloworld;

// [START walkthrough_pubsub]
exports.helloworld = 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]
24 changes: 24 additions & 0 deletions functions/log2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's different enough about these samples to necessitate two of them?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple "hello world" samples in the docs (I don't know why), which is where these samples are used. I think this particular sample will go away after the docs are re-organized.


# Google Cloud Functions message sample #2

This sample shows writing to logs in a Cloud Function.

View the [documentation][docs] or the [source code][code].

[docs]: https://cloud.google.com/functions/walkthroughs
[code]: index.js

## Deploy

This example deploys the function with an HTTP trigger.

gcloud alpha functions deploy helloworld --bucket <your-bucket-name> --trigger-http

## Test

gcloud alpha functions call helloworld

You can also use `curl` to trigger the function:

curl -X POST https://<your-project-region>.<your-project-id>.cloudfunctions.net/helloworld
Loading