diff --git a/.travis.yml b/.travis.yml index c1ca1d50d94..b347bf1cfb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 diff --git a/README.md b/README.md index 58fd0d28294..32b3029a866 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,33 @@ # Google Cloud Platform NodeJS Samples -This repository holds the samples used in the nodejs documentation on -[cloud.google.com/nodejs](https://cloud.google.com/nodejs). +This repository holds Node.js samples used throught [cloud.google.com](). [![Build Status](https://travis-ci.org/GoogleCloudPlatform/nodejs-docs-samples.svg)](https://travis-ci.org/GoogleCloudPlatform/nodejs-docs-samples) +## Table of Contents + +* [Google App Engine](#google-app-engine) +* [Google Cloud Logging](#google-cloud-logging) +* [Google Cloud Storage](#google-cloud-storage) +* [Google Prediction API](#google-prediction-api) +* [Other Example Apps](#other-example-apps) +* [More Information](#more-information) +* [Contributing](#contributing) +* [License](#license) + ## Google App Engine This is a collection of samples and instructions to run common nodejs frameworks and applications on [Google App Engine](http://cloud.google.com/nodejs). -### Frameworks +__Google (Cloud) Products__ + +- Google Analytics - [Source code][aeanalytics_1] +- Google Cloud Logging - [Source code][aelogging_1] +- Google Cloud Pub/Sub - [Source code][aepubsub_1] +- Google Cloud Storage - [Source code][aestorage_1] + +__Frameworks__ - Express.js - [Source code][express_1] | [App Engine Tutorial][express_2] | [Live demo][express_3] | [Documentation][express_4] - Express.js + Memcached Sessions - [Source code][express_5] | [Documentation][express_6] @@ -22,25 +39,37 @@ and applications on [Google App Engine](http://cloud.google.com/nodejs). - Restify.js - [Source code][restify_1] | [App Engine Tutorial][restify_2] | [Live demo][restify_3] | [Documentation][restify_4] - Sails.js - [Source code][sails_1] | [App Engine Tutorial][sails_2] | [Live demo][sails_3] | [Documentation][sails_4] -### Databases +__Databases__ +- Google Cloud Datastore - [Source code][aedatastore_1] +- Google Cloud SQL - [Source code][aecloudsql_1] +- Memcached - [Source code][memcached_1] - MongoDB - [Source code][mongodb_1] | [App Engine Tutorial][mongodb_2] | [Documentation][mongodb_3] - Redis - [Source code][redis_1] | [App Engine Tutorial][redis_2] | [Documentation][redis_3] -### Tools +__Tools__ - gcloud-node - [Source code][gcloud_1] | [Documentation][gcloud_2] - Bower - [Source code][bower_1] | [App Engine Tutorial][bower_2] | [Documentation][bower_3] - Grunt - [Source code][grunt_1] | [App Engine Tutorial][grunt_2] | [Live demo][grunt_3] | [Documentation][grunt_4] - Mailgun - [Source code][mailgun_1] | [App Engine Tutorial][mailgun_2] | [Documentation][mailgun_3] - Sendgrid - [Source code][sendgrid_1] | [App Engine Tutorial][sendgrid_2] | [Documentation][sendgrid_3] +- Twilio - [Source code][twilio_1] - Webpack - [Source code][webpack_1] | [App Engine Tutorial][webpack_2] | [Documentation][webpack_3] +- WebSockets - [Source code][websockets_1] + +__Other Examples__ + +- Express.js Hello World - [Source code][expresshw_1] +- Extending the runtime - [Source code][aeextending_1] +- Reading/writing from/to disk - [Source code][aedisk_1] +- Serving static files - [Source code][aestaticfiles_1] ## Google Storage - Auth sample - [Source code][storage_1] | [Google Cloud Docs][storage_2] -## Example Apps +## Other Example Apps - nodejs-getting-started - [Source code][nodejs_1] | [App Engine Tutorial 1][nodejs_2] | [App Engine Tutorial 2][nodejs_3] - gcloud-node-todos - [Source code][todos_1] @@ -54,7 +83,7 @@ and applications on [Google App Engine](http://cloud.google.com/nodejs). - [Using the `gcloud` npm module](https://googlecloudplatform.github.io/gcloud-node/#/) - [Logging to Google Cloud with Winston](https://github.com/GoogleCloudPlatform/winston-gae) -## Contributing changes +## Contributing Contributions welcome! @@ -68,6 +97,9 @@ See [CONTRIBUTING.md](https://github.com/GoogleCloudPlatform/nodejs-docs-samples 1. Start Redis 1. Start Memcached 1. Set the `TEST_PROJECT_ID` environment variable to id of your project +1. Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path to +a service account file. You can download one from your Google project's +"permissions" page. 1. `npm test` Since the tests use [Mocha.js](https://mochajs.org/), you can use the `--grep` @@ -77,40 +109,35 @@ option causes the matched tests to be excluded instead of included. __Run only the tests that match a pattern:__ -``` -npm test -- -- --grep -``` + npm test -- -- --grep __Only run the tests for the `datastore` sample:__ -``` -npm test -- -- --grep datastore -``` + npm test -- -- --grep datastore __Skip the tests that match a pattern:__ -``` -npm test -- -- --grep --invert -``` + npm test -- -- --grep --invert __Run all but the `datastore` tests:__ -``` -npm test -- -- --grep datastore --invert -``` + npm test -- -- --grep datastore --invert __Skip the tests that require Redis and Memcached:__ -``` -npm test -- -- --grep "express-memcached-session|redis" --invert -``` + npm test -- -- --grep "express-memcached-session|redis" --invert -## Licensing +## License Apache Version 2.0 See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/LICENSE) +[aeanalytics_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/analytics +[aelogging_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/logging +[aepubsub_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/pubsub +[aestorage_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/storage + [storage_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/storage/authSample.js [storage_2]: https://cloud.google.com/storage/docs/authentication#acd-examples @@ -156,6 +183,10 @@ See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/ma [sails_3]: http://sails-dot-nodejs-docs-samples.appspot.com [sails_4]: http://sailsjs.org/ +[aedatastore_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/datastore +[aecloudsql_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/cloudsql +[memcached_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/memcached + [mongodb_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/mongodb [mongodb_2]: https://cloud.google.com/nodejs/resources/databases/mongo [mongodb_3]: https://docs.mongodb.org/ @@ -184,10 +215,19 @@ See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/ma [sendgrid_2]: https://cloud.google.com/nodejs/resources/tools/sendgrid [sendgrid_3]: http://sendgrid.com/ +[twilio_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/twilio + [webpack_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/webpack [webpack_2]: https://cloud.google.com/nodejs/resources/tools/webpack [webpack_3]: https://webpack.github.io/ +[websockets_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/websockets + +[expresshw_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/hello-world +[aedisk_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/disk +[aeextending_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/extending-runtime +[aestaticfiles_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/static-files + [nodejs_1]: https://github.com/GoogleCloudPlatform/nodejs-getting-started [nodejs_2]: https://cloud.google.com/nodejs/getting-started/hello-world [nodejs_3]: https://cloud.google.com/nodejs/getting-started/tutorial-app diff --git a/appengine/README.md b/appengine/README.md new file mode 100644 index 00000000000..1f1291e962a --- /dev/null +++ b/appengine/README.md @@ -0,0 +1,51 @@ +# Google App Engine Node.js Samples + +These are samples for using Node.js on Google App Engine Managed VMs. These +samples are referenced from the [docs](https://cloud.google.com/appengine/docs). + +See our other [Google Cloud Platform github repos](https://github.com/GoogleCloudPlatform) +for sample applications and scaffolding for other frameworks and use cases. + +## Run Locally + +Some samples have specific instructions. If there is a README in the sample +folder, please refer to it for any additional steps required to run the sample. + +In general, the samples typically require: + +1. Install the [Google Cloud SDK](https://cloud.google.com/sdk/), including the +[gcloud tool](https://cloud.google.com/sdk/gcloud/), and +[gcloud app component](https://cloud.google.com/sdk/gcloud-app). +1. Setup the gcloud tool. This provides authentication to Google Cloud APIs and +services. + + gcloud init + +1. Clone this repo. + + git clone https://github.com/GoogleCloudPlatform/.git + +1. Open a sample folder, install dependencies, and run the sample: + + cd / + npm install + npm start + +1. Visit the application at [http://localhost:8080](http://localhost:8080). + +## Deploying + +Some samples in this repositories may have special deployment instructions. +Refer to the README file in the sample folder. + +1. Use the [Google Developers Console](https://console.developer.google.com) to +create a project/app id. (App id and project id are identical.) +1. Setup the gcloud tool, if you haven't already. + + gcloud init + +1. Use gcloud to deploy your app. + + gcloud preview app deploy + +1. Awesome! Your application is now live at `your-app-id.appspot.com`. diff --git a/appengine/analytics/README.md b/appengine/analytics/README.md new file mode 100644 index 00000000000..9e8fdd7381e --- /dev/null +++ b/appengine/analytics/README.md @@ -0,0 +1,23 @@ +# Google Analytics Measurement Protocol on Google App Engine + +This sample demonstrates how to use the [Google Analytics Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/v1/) +(or any other SQL server) on [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Setup + +Before you can run or deploy the sample, you need to do the following: + +1. Create a Google Analytics Property and obtain the Tracking ID. +1. Update the environment variables in in `app.yaml` with your Tracking ID. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +To run locally, set the environment variables via your shell before running the +sample: + + export GA_TRACKING_ID= + npm install + npm start diff --git a/appengine/analytics/app.js b/appengine/analytics/app.js new file mode 100644 index 00000000000..4aab53d0ea9 --- /dev/null +++ b/appengine/analytics/app.js @@ -0,0 +1,76 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); +var request = require('request'); + +var app = express(); + +// The following environment variable is set by app.yaml when running on GAE, +// but will need to be manually set when running locally. See README.md. +var GA_TRACKING_ID = process.env.GA_TRACKING_ID; + +function trackEvent(category, action, label, value, cb) { + var data = { + v: '1', // API Version. + tid: GA_TRACKING_ID, // Tracking ID / Property ID. + // Anonymous Client Identifier. Ideally, this should be a UUID that + // is associated with particular user, device, or browser instance. + cid: '555', + t: 'event', // Event hit type. + ec: category, // Event category. + ea: action, // Event action. + el: label, // Event label. + ev: value, // Event value. + }; + + request.post( + 'http://www.google-analytics.com/collect', { + form: data + }, + function(err, response) { + if (err) { return cb(err); } + if (response.statusCode !== 200) { + return cb(new Error('Tracking failed')); + } + cb(); + } + ); +} + +app.get('/', function(req, res, next) { + trackEvent( + 'Example category', + 'Example action', + 'Example label', + '100', // Event value must be numeric. + function(err) { + // This sample treats an event tracking error as a fatal error. Depending + // on your application's needs, failing to track an event may not be + // considered an error. + if (err) { return next(err); } + res.status(200).send('Event tracked.'); + }); +}); + +// Start the server +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/analytics/app.yaml b/appengine/analytics/app.yaml new file mode 100644 index 00000000000..ab6c77cd436 --- /dev/null +++ b/appengine/analytics/app.yaml @@ -0,0 +1,25 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env] +env_variables: + GA_TRACKING_ID: +# [END env] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/analytics/package.json b/appengine/analytics/package.json new file mode 100644 index 00000000000..01a687cc44c --- /dev/null +++ b/appengine/analytics/package.json @@ -0,0 +1,20 @@ +{ + "name": "appengine-analytics", + "description": "Sample for Google Analytics Measurement Protocol on Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "request": "^2.67.0" + } +} diff --git a/appengine/bower/README.md b/appengine/bower/README.md index 5db00803c34..7c6f12f1560 100644 --- a/appengine/bower/README.md +++ b/appengine/bower/README.md @@ -1,4 +1,4 @@ -## Bower on Google App Engine +# Bower on Google App Engine > [Bower][1]: A package manager for the web. diff --git a/appengine/bower/app.yaml b/appengine/bower/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/bower/app.yaml +++ b/appengine/bower/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/bower/package.json b/appengine/bower/package.json index 76bcd4e7a0b..76e4e8c1de3 100644 --- a/appengine/bower/package.json +++ b/appengine/bower/package.json @@ -4,13 +4,14 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node server.js", "postinstall": "bower install --config.interactive=false", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "bower": "^1.6.5", diff --git a/appengine/bower/server.js b/appengine/bower/server.js index d5d167b08eb..b5e5bee735d 100644 --- a/appengine/bower/server.js +++ b/appengine/bower/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/bower/views/index.jade b/appengine/bower/views/index.jade index 90be1eddde1..e7c826d46cf 100644 --- a/appengine/bower/views/index.jade +++ b/appengine/bower/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/cloudsql/README.md b/appengine/cloudsql/README.md new file mode 100644 index 00000000000..87a3fd413fc --- /dev/null +++ b/appengine/cloudsql/README.md @@ -0,0 +1,40 @@ +# Node.js Cloud SQL sample on Google App Engine + +This sample demonstrates how to use [Cloud SQL](https://cloud.google.com/sql/) +on [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Setup + +Before you can run or deploy the sample, you will need to do the following: + +1. Create a Cloud SQL instance. You can do this from the [Google Developers Console](https://console.developers.google.com) +or via the [Cloud SDK](https://cloud.google.com/sdk). To create it via the SDK +use the following command: + + gcloud sql instances create [your-instance-name] \ + --assign-ip \ + --authorized-networks 0.0.0.0/0 \ + --tier D0 + +1. Create a new user and database for the application. The easiest way to do +this is via the [Google Developers Console](https://console.developers.google.com/project/_/sql/instances/example-instance2/access-control/users). +Alternatively, you can use MySQL tools such as the command line client or +workbench. +1. Update the values in in `app.yaml` with your instance configuration. +1. Finally, run `create_tables.js` to ensure that the database is properly +configured and to create the tables needed for the sample. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +To run locally, set the environment variables via your shell before running the +sample: + + export MYSQL_HOST= + export MYSQL_USER= + export MYSQL_PASSWORD= + export MYSQL_DATABASE= + npm install + npm start diff --git a/appengine/cloudsql/app.js b/appengine/cloudsql/app.js new file mode 100644 index 00000000000..9ae35a2f026 --- /dev/null +++ b/appengine/cloudsql/app.js @@ -0,0 +1,73 @@ +// 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. +// [START app] +'use strict'; + +var format = require('util').format; +var express = require('express'); +var mysql = require('mysql'); + +var app = express(); +app.enable('trust proxy'); + +// These environment variables are set by app.yaml when running on GAE, but +// will need to be manually set when running locally. +// If you're connecting via SSL you will need to specify your certs here, see +// https://github.com/felixge/node-mysql/#ssl-options +var connection = mysql.createConnection({ + host: process.env.MYSQL_HOST, + user: process.env.MYSQL_USER, + password: process.env.MYSQL_PASSWORD, + database: process.env.MYSQL_DATABASE +}); + +app.get('/', function(req, res, next) { + + // Add this visit to the database + var visit = { + timestamp: new Date(), + userIp: req.ip + }; + + connection.query('INSERT INTO `visits` SET ?', visit, function(err) { + if (err) { return next(err); } + + // Query the last 10 visits from the database. + connection.query( + 'SELECT `timestamp`, `userIp` FROM `visits` ORDER BY `timestamp` DESC ' + + 'LIMIT 10', + function(err, results) { + if (err) { return next(err); } + + var visits = results.map(function(visit) { + return format( + 'Time: %s, Addr: %s', + visit.timestamp, + visit.userIp); + }); + + var output = format('Last 10 visits:\n%s', visits.join('\n')); + + res.set('Content-Type', 'text/plain'); + res.status(200).send(output); + }); + }); +}); + +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/cloudsql/app.yaml b/appengine/cloudsql/app.yaml new file mode 100644 index 00000000000..691f620e2ee --- /dev/null +++ b/appengine/cloudsql/app.yaml @@ -0,0 +1,30 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env] +env_variables: + # Replace user, password, and host with the values obtained when + # configuring your Cloud SQL instance. + MYSQL_HOST: + MYSQL_USER: + MYSQL_PASSWORD: + MYSQL_DATABASE: +# [END env] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/cloudsql/create_tables.js b/appengine/cloudsql/create_tables.js new file mode 100644 index 00000000000..bb36c26b359 --- /dev/null +++ b/appengine/cloudsql/create_tables.js @@ -0,0 +1,43 @@ +// 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. + +// [START all] +'use strict'; + +var mysql = require('mysql'); +var prompt = require('prompt'); + +prompt.start(); + +prompt.get(['host', 'user', 'password', 'database'], function(err, config) { + if (err) { return; } + + config.multipleStatements = true; + + var connection = mysql.createConnection(config); + + connection.query( + 'CREATE TABLE `visits` (' + + ' `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,' + + ' `timestamp` DATETIME NULL,' + + ' `userIp` VARCHAR(46) NULL,' + + ' PRIMARY KEY (`id`));', + function(err) { + if (err) { throw err; } + console.log('Done!'); + connection.end(); + } + ); +}); +// [END all] diff --git a/appengine/cloudsql/package.json b/appengine/cloudsql/package.json new file mode 100644 index 00000000000..493e3e2049c --- /dev/null +++ b/appengine/cloudsql/package.json @@ -0,0 +1,21 @@ +{ + "name": "appengine-cloudsql", + "description": "Sample for Google Cloud SQL on Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "mysql": "^2.10.2", + "prompt": "^0.2.14" + } +} diff --git a/appengine/datastore/README.md b/appengine/datastore/README.md new file mode 100644 index 00000000000..5d0224ba833 --- /dev/null +++ b/appengine/datastore/README.md @@ -0,0 +1,25 @@ +# Node.js Cloud Datastore sample for Google App Engine + +This sample demonstrates how to use [Cloud Datastore](https://cloud.google.com/datastore/) +on [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Setup + +Before you can run or deploy the sample, you will need to enable the Cloud +Datastore API in the [Google Developers Console](https://console.developers.google.com/project/_/apiui/apiview/datastore/overview). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +When running locally, you can use the [Google Cloud SDK](https://cloud.google.com/sdk) +to provide authentication to use Google Cloud APIs: + + gcloud init + +Set the `GCLOUD_PROJECT` environment variable to your Project ID before starting your application: + + export GCLOUD_PROJECT= + npm install + npm start diff --git a/appengine/datastore/app.js b/appengine/datastore/app.js new file mode 100644 index 00000000000..e627767d69b --- /dev/null +++ b/appengine/datastore/app.js @@ -0,0 +1,71 @@ +// 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. + +// [START app] +'use strict'; + +var format = require('util').format; +var express = require('express'); +var gcloud = require('gcloud'); + +var app = express(); +app.enable('trust proxy'); + +var dataset = gcloud.datastore.dataset({ + // This environment variable is set by app.yaml when running on GAE, but will + // need to be manually set when running locally. + projectId: process.env.GCLOUD_PROJECT || process.env.TEST_PROJECT_ID +}); + +app.get('/', function(req, res, next) { + // Add this visit to the datastore + dataset.save({ + key: dataset.key('visit'), + data: { + timestamp: new Date(), + userIp: req.ip + } + }, function(err) { + if (err) { return next(err); } + + // Query the last 10 visits from the datastore. + var query = dataset.createQuery('visit') + .order('-timestamp') + .limit(10); + + dataset.runQuery(query, function(err, entities) { + if (err) { return next(err); } + + var visits = entities.map(function(entity) { + return format( + 'Time: %s, Addr: %s', + entity.data.timestamp, + entity.data.userIp); + }); + + var output = format('Last 10 visits:\n%s', visits.join('\n')); + + res.set('Content-Type', 'text/plain'); + res.status(200).send(output); + }); + }); +}); + +/* Start the server */ +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/datastore/app.yaml b/appengine/datastore/app.yaml new file mode 100644 index 00000000000..df0a0f963b3 --- /dev/null +++ b/appengine/datastore/app.yaml @@ -0,0 +1,25 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env_variables] +env_variables: + GCLOUD_PROJECT: +# [END env_variables] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/datastore/package.json b/appengine/datastore/package.json new file mode 100644 index 00000000000..ab582e87463 --- /dev/null +++ b/appengine/datastore/package.json @@ -0,0 +1,20 @@ +{ + "name": "appengine-datastore", + "description": "Sample for Google Cloud Datastore on Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "^4.2.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "gcloud": "^0.27.0" + } +} diff --git a/appengine/disk/README.md b/appengine/disk/README.md new file mode 100644 index 00000000000..b26859230fb --- /dev/null +++ b/appengine/disk/README.md @@ -0,0 +1,8 @@ +# Simple sample for Node.js on Google App Engine + +This sample demonstrates reading from and writing to disk on [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/disk/app.js b/appengine/disk/app.js new file mode 100644 index 00000000000..c2814e9b5e4 --- /dev/null +++ b/appengine/disk/app.js @@ -0,0 +1,48 @@ +// 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. + +// [START app] +'use strict'; + +var fs = require('fs'); +var util = require('util'); +var express = require('express'); + +var app = express(); +app.enable('trust proxy'); + +app.get('/', function(req, res, next) { + var instanceId = process.env.GAE_MODULE_INSTANCE || '1'; + var userIp = util.format('%s\n', req.ip); + + fs.appendFile('/tmp/seen.txt', userIp, function(err) { + if (err) { return next(err); } + + fs.readFile('/tmp/seen.txt', function(err, data) { + if (err) { return next(err); } + + res.set('Content-Type', 'text/plain'); + res.status(200).send(util.format( + 'Instance: %s\n' + + 'Seen: \n%s', instanceId, data)); + }); + }); +}); + +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/disk/app.yaml b/appengine/disk/app.yaml new file mode 100644 index 00000000000..7d5f4a59226 --- /dev/null +++ b/appengine/disk/app.yaml @@ -0,0 +1,21 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] + diff --git a/appengine/disk/package.json b/appengine/disk/package.json new file mode 100644 index 00000000000..01839f003a6 --- /dev/null +++ b/appengine/disk/package.json @@ -0,0 +1,19 @@ +{ + "name": "appengine-disk", + "version": "0.0.1", + "description": "Simple sample for Node.js on Google App Engine", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3" + } +} diff --git a/appengine/express-memcached-session/README.md b/appengine/express-memcached-session/README.md index 66ee94eac40..d75e107c881 100644 --- a/appengine/express-memcached-session/README.md +++ b/appengine/express-memcached-session/README.md @@ -1,4 +1,4 @@ -## Express.js + Memcached Sessions on Google App Engine +# Express.js + Memcached Sessions on Google App Engine This is a simple guide to using memcached for session state while running [Express.js](http://expressjs.com/) on Google App Engine. Each Google App Engine @@ -12,10 +12,8 @@ session data in memcached. If you haven't already, copy the repository to your local machine by entering the following command in your terminal window: -``` -$ git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git -$ cd nodejs-docs-samples/appengine/express-memcached-session -``` + git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git + cd nodejs-docs-samples/appengine/express-memcached-session Alternatively, you can [download the sample][download] as a zip and extract it. @@ -23,21 +21,15 @@ Alternatively, you can [download the sample][download] as a zip and extract it. 1. Install dependencies. Enter the following command: - ``` - $ npm install - ``` + npm install -2. Run the start script. +1. Run the start script. - ```` - $ npm start - ``` + npm start -3. In your web browser, enter the following address: +1. In your web browser, enter the following address: - ``` - $ http://localhost:8080 - ``` + http://localhost:8080 You can see the sample app displayed in the page. This page was delivered by the Express.js web server running on your computer. @@ -48,44 +40,36 @@ In your terminal window, press Ctrl+C to exit the web server. In your terminal window, enter the following command to deploy the sample: -``` -$ gcloud preview app deploy app.yaml --promote -``` + gcloud preview app deploy ### See the app run in the cloud In your web browser, enter the following address: -``` -https://.appspot.com -``` + https://.appspot.com -For convenience, you can use an npm script to run the gcloud command. Add these lines to your package.json file: +For convenience, you can use an npm script to run the gcloud command. Add these +lines to your package.json file: -``` -"scripts": { - "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml --promote --project " -} -``` + "scripts": { + "start": "node server.js", + "deploy": "gcloud preview app deploy" + } At the terminal you can now run the following command to deploy your application: -``` -$ npm run deploy -``` + npm run deploy ## Configuration -Every Managed VMs application requires an app.yaml file to describe its deployment configuration. +Every Managed VMs application requires an app.yaml file to describe its +deployment configuration. -```yaml -runtime: nodejs -vm: true -env_variables: - PORT: 8080 - MEMCACHE_URL: memcache:11211 -``` + runtime: nodejs + vm: true + env_variables: + PORT: 8080 + MEMCACHE_URL: memcache:11211 Notice the `MEMCACHE_URL` environment variable–this is where you can reach your standard memcached cluster across instances. diff --git a/appengine/express-memcached-session/app.yaml b/appengine/express-memcached-session/app.yaml index 5fc9a84bbc0..1bc4008679c 100644 --- a/appengine/express-memcached-session/app.yaml +++ b/appengine/express-memcached-session/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -11,9 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +# [START app_yaml] runtime: nodejs vm: true env_variables: MEMCACHE_URL: localhost:11211 + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/express-memcached-session/package.json b/appengine/express-memcached-session/package.json index eb02b25fa9b..bddd73753a5 100644 --- a/appengine/express-memcached-session/package.json +++ b/appengine/express-memcached-session/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "connect-memcached": "^0.1.0", diff --git a/appengine/express-memcached-session/server.js b/appengine/express-memcached-session/server.js index e9827248a86..d80070e667b 100644 --- a/appengine/express-memcached-session/server.js +++ b/appengine/express-memcached-session/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/app.js b/appengine/express/app.js index f0b53aa7051..f3d127ad908 100644 --- a/appengine/express/app.js +++ b/appengine/express/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/app.yaml b/appengine/express/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/express/app.yaml +++ b/appengine/express/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/express/package.json b/appengine/express/package.json index 588cf4ee889..e6a232a34d3 100644 --- a/appengine/express/package.json +++ b/appengine/express/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node ./bin/www", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "body-parser": "^1.14.1", diff --git a/appengine/express/public/stylesheets/style.css b/appengine/express/public/stylesheets/style.css index 3f27236c043..6b5fc95dac7 100644 --- a/appengine/express/public/stylesheets/style.css +++ b/appengine/express/public/stylesheets/style.css @@ -1,4 +1,4 @@ -/** Copyright 2015, Google, Inc. +/** 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 diff --git a/appengine/express/routes/index.js b/appengine/express/routes/index.js index 065440b595a..d7028a9fb83 100644 --- a/appengine/express/routes/index.js +++ b/appengine/express/routes/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/routes/users.js b/appengine/express/routes/users.js index ceb2144cad6..f64cc260a6f 100644 --- a/appengine/express/routes/users.js +++ b/appengine/express/routes/users.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/views/error.jade b/appengine/express/views/error.jade index b9dd8f8eb82..5e4cc70dccc 100644 --- a/appengine/express/views/error.jade +++ b/appengine/express/views/error.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/views/index.jade b/appengine/express/views/index.jade index 0f4bfc7b7b9..a62210cbe78 100644 --- a/appengine/express/views/index.jade +++ b/appengine/express/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/express/views/layout.jade b/appengine/express/views/layout.jade index 08c319bfe38..c027171f059 100644 --- a/appengine/express/views/layout.jade +++ b/appengine/express/views/layout.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/extending-runtime/.dockerignore b/appengine/extending-runtime/.dockerignore new file mode 100644 index 00000000000..52ec99de335 --- /dev/null +++ b/appengine/extending-runtime/.dockerignore @@ -0,0 +1,6 @@ +node_modules +.dockerignore +Dockerfile +.git +.hg +.svn diff --git a/appengine/extending-runtime/Dockerfile b/appengine/extending-runtime/Dockerfile new file mode 100755 index 00000000000..ea3b43825af --- /dev/null +++ b/appengine/extending-runtime/Dockerfile @@ -0,0 +1,18 @@ +# This is the standard Node.js runtime image. It is essentially Debian with +# Node.js pre-installed. +FROM gcr.io/google_appengine/nodejs + +# Install something custom +RUN apt-get update && apt-get install -y fortunes + +# Install a particular version of Node.js +RUN install_node v4.2.3 + +# Copy application code. +COPY . /app/ + +# Install dependencies. +RUN npm --unsafe-perm install + +# Run the app, default is "npm start" +CMD npm start-on-prod diff --git a/appengine/extending-runtime/README.md b/appengine/extending-runtime/README.md new file mode 100644 index 00000000000..96916f04979 --- /dev/null +++ b/appengine/extending-runtime/README.md @@ -0,0 +1,11 @@ +# Sample for extending the Google App Engine Managed VMs Node.js runtime + +This sample demonstrates how to create a custom Dockerfile and extend the +Node.js runtime used by [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +The Dockerfile in this sample will automatically be used during deployment. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/extending-runtime/app.js b/appengine/extending-runtime/app.js new file mode 100644 index 00000000000..c84fca332a6 --- /dev/null +++ b/appengine/extending-runtime/app.js @@ -0,0 +1,39 @@ +// 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. + +// [START app] +'use strict'; + +var exec = require('child_process').exec; +var express = require('express'); + +var app = express(); + +app.get('/', function(req, res, next) { + // Get the output from the "fortune" program. This is installed into the + // environment by the Dockerfile. + exec('/usr/games/fortune', function(err, stdout) { + if (err) { return next(err); } + + res.set('Content-Type', 'text/plain'); + res.status(200).send(stdout); + }); +}); + +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/extending-runtime/app.yaml b/appengine/extending-runtime/app.yaml new file mode 100644 index 00000000000..d67428f6f75 --- /dev/null +++ b/appengine/extending-runtime/app.yaml @@ -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. + +# [START app_yaml] +runtime: custom +vm: true + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/extending-runtime/package.json b/appengine/extending-runtime/package.json new file mode 100644 index 00000000000..f26e063efbb --- /dev/null +++ b/appengine/extending-runtime/package.json @@ -0,0 +1,20 @@ +{ + "name": "appengine-extending-runtime", + "description": "Sample for extending the Google App Engine Managed VMs Node.js runtime", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "start-on-prod": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3" + } +} diff --git a/appengine/geddy/app.yaml b/appengine/geddy/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/geddy/app.yaml +++ b/appengine/geddy/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/geddy/package.json b/appengine/geddy/package.json index 029a208602d..09dd85f9280 100644 --- a/appengine/geddy/package.json +++ b/appengine/geddy/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, @@ -11,7 +12,7 @@ "prestart": "GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && geddy gen secret", "start": "geddy", "debug": "geddy --debug", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "geddy": "^13.0.8" diff --git a/appengine/grunt/Gruntfile.js b/appengine/grunt/Gruntfile.js index e08b05153d2..6fca92d6ea0 100644 --- a/appengine/grunt/Gruntfile.js +++ b/appengine/grunt/Gruntfile.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/app.yaml b/appengine/grunt/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/grunt/app.yaml +++ b/appengine/grunt/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/grunt/package.json b/appengine/grunt/package.json index aa33e223f1f..61325c0515c 100644 --- a/appengine/grunt/package.json +++ b/appengine/grunt/package.json @@ -4,13 +4,14 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node ./src/bin/www", "postinstall": "grunt build", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "body-parser": "^1.14.1", diff --git a/appengine/grunt/src/app.js b/appengine/grunt/src/app.js index f0b53aa7051..f3d127ad908 100644 --- a/appengine/grunt/src/app.js +++ b/appengine/grunt/src/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/src/public/stylesheets/style.css b/appengine/grunt/src/public/stylesheets/style.css index 724972691bf..2040139a4d9 100644 --- a/appengine/grunt/src/public/stylesheets/style.css +++ b/appengine/grunt/src/public/stylesheets/style.css @@ -1,4 +1,4 @@ -/** Copyright 2015, Google, Inc. +/** 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 diff --git a/appengine/grunt/src/routes/index.js b/appengine/grunt/src/routes/index.js index c66cdf01024..851a2c5ed4e 100644 --- a/appengine/grunt/src/routes/index.js +++ b/appengine/grunt/src/routes/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/src/routes/users.js b/appengine/grunt/src/routes/users.js index 92e1e039d4b..39001d0b498 100644 --- a/appengine/grunt/src/routes/users.js +++ b/appengine/grunt/src/routes/users.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/src/views/error.jade b/appengine/grunt/src/views/error.jade index b9dd8f8eb82..5e4cc70dccc 100644 --- a/appengine/grunt/src/views/error.jade +++ b/appengine/grunt/src/views/error.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/src/views/index.jade b/appengine/grunt/src/views/index.jade index 0f4bfc7b7b9..a62210cbe78 100644 --- a/appengine/grunt/src/views/index.jade +++ b/appengine/grunt/src/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/grunt/src/views/layout.jade b/appengine/grunt/src/views/layout.jade index fd0efcf923e..5dc82d8d1dd 100644 --- a/appengine/grunt/src/views/layout.jade +++ b/appengine/grunt/src/views/layout.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/hapi/app.yaml b/appengine/hapi/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/hapi/app.yaml +++ b/appengine/hapi/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/hapi/index.js b/appengine/hapi/index.js index 8defc9ad7c3..3c1ac195c9f 100644 --- a/appengine/hapi/index.js +++ b/appengine/hapi/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/hapi/package.json b/appengine/hapi/package.json index 8b378312f78..659074c5d94 100644 --- a/appengine/hapi/package.json +++ b/appengine/hapi/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node index.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "hapi": "^10.5.0" diff --git a/appengine/hello-world/README.md b/appengine/hello-world/README.md new file mode 100644 index 00000000000..2f7c622afc1 --- /dev/null +++ b/appengine/hello-world/README.md @@ -0,0 +1,8 @@ +# Simple Hello World Node.js sample for Google App Engine + +This sample demonstrates a tiny Hello World Node.js app for [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/hello-world/app.js b/appengine/hello-world/app.js new file mode 100644 index 00000000000..c89a001d7d9 --- /dev/null +++ b/appengine/hello-world/app.js @@ -0,0 +1,32 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); + +var app = express(); + +app.get('/', function(req, res) { + res.status(200).send('Hello, world!'); +}); + +// Start the server +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/hello-world/app.yaml b/appengine/hello-world/app.yaml new file mode 100644 index 00000000000..4748785677f --- /dev/null +++ b/appengine/hello-world/app.yaml @@ -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. + +# [START app_yaml] +runtime: nodejs +vm: true + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/hello-world/package.json b/appengine/hello-world/package.json new file mode 100644 index 00000000000..80b40f5877d --- /dev/null +++ b/appengine/hello-world/package.json @@ -0,0 +1,19 @@ +{ + "name": "appengine-hello-world", + "description": "Simple Hello World Node.js sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3" + } +} diff --git a/appengine/koa/app.js b/appengine/koa/app.js index d9a1aa8b123..7bce9b41c80 100644 --- a/appengine/koa/app.js +++ b/appengine/koa/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/koa/app.yaml b/appengine/koa/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/koa/app.yaml +++ b/appengine/koa/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/koa/package.json b/appengine/koa/package.json index 8693283676c..a169568d6c3 100644 --- a/appengine/koa/package.json +++ b/appengine/koa/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node --harmony app.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "koa": "^1.0.0" diff --git a/appengine/kraken/Gruntfile.js b/appengine/kraken/Gruntfile.js index 4d9af41ee15..dada648b747 100644 --- a/appengine/kraken/Gruntfile.js +++ b/appengine/kraken/Gruntfile.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/kraken/app.yaml b/appengine/kraken/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/kraken/app.yaml +++ b/appengine/kraken/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/kraken/controllers/index.js b/appengine/kraken/controllers/index.js index 8a87e5c8a8a..30f2e64b049 100644 --- a/appengine/kraken/controllers/index.js +++ b/appengine/kraken/controllers/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/kraken/index.js b/appengine/kraken/index.js index 92a89291302..a3250ff0c33 100644 --- a/appengine/kraken/index.js +++ b/appengine/kraken/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/kraken/models/index.js b/appengine/kraken/models/index.js index 2a435176399..6dabd1a4b22 100644 --- a/appengine/kraken/models/index.js +++ b/appengine/kraken/models/index.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/kraken/package.json b/appengine/kraken/package.json index 857702fde61..8d92049ff88 100644 --- a/appengine/kraken/package.json +++ b/appengine/kraken/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, @@ -12,7 +13,7 @@ "build": "node_modules/grunt-cli/bin/grunt build", "all": "npm run build && npm run test", "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "construx": "^1.0.0", diff --git a/appengine/kraken/server.js b/appengine/kraken/server.js index 7128e6d7cad..0728f27004c 100644 --- a/appengine/kraken/server.js +++ b/appengine/kraken/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/logging/README.md b/appengine/logging/README.md new file mode 100644 index 00000000000..247d91cc010 --- /dev/null +++ b/appengine/logging/README.md @@ -0,0 +1,8 @@ +# Node.js logging sample for Google App Engine + +This sample demonstrates logging in a Node.js app for [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/logging/app.js b/appengine/logging/app.js new file mode 100644 index 00000000000..a744641f761 --- /dev/null +++ b/appengine/logging/app.js @@ -0,0 +1,44 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); +var app = express(); + +var winston = require('winston'); +require('winston-gae'); + +var logger = new winston.Logger({ + levels: winston.config.GoogleAppEngine.levels, + transports: [ + new winston.transports.GoogleAppEngine({ + // capture logs at emergency and above (all levels) + level: 'emergency' + }) + ] +}); + +app.get('/', function(req, res) { + logger.info('Request from %s', req.ip); + res.status(200).send('Logged'); +}); + +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/logging/app.yaml b/appengine/logging/app.yaml new file mode 100644 index 00000000000..4748785677f --- /dev/null +++ b/appengine/logging/app.yaml @@ -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. + +# [START app_yaml] +runtime: nodejs +vm: true + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/logging/package.json b/appengine/logging/package.json new file mode 100644 index 00000000000..1cc70141c54 --- /dev/null +++ b/appengine/logging/package.json @@ -0,0 +1,21 @@ +{ + "name": "appengine-logging", + "description": "Node.js logging sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "winston": "^2.1.1", + "winston-gae": "^0.1.0" + } +} diff --git a/appengine/loopback/app.yaml b/appengine/loopback/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/loopback/app.yaml +++ b/appengine/loopback/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/loopback/common/models/person.js b/appengine/loopback/common/models/person.js index f68d56eccd5..5af23fd20e4 100644 --- a/appengine/loopback/common/models/person.js +++ b/appengine/loopback/common/models/person.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/loopback/package.json b/appengine/loopback/package.json index 8ff6f826d2d..8ca30ac221d 100644 --- a/appengine/loopback/package.json +++ b/appengine/loopback/package.json @@ -4,13 +4,14 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "pretest": "jshint .", "start": "node server/server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "compression": "^1.0.3", diff --git a/appengine/loopback/server/server.js b/appengine/loopback/server/server.js index 04a5fe5be60..02277137c15 100644 --- a/appengine/loopback/server/server.js +++ b/appengine/loopback/server/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/mailgun/app.js b/appengine/mailgun/app.js index 3490cd6aee8..e69b24e0d12 100644 --- a/appengine/mailgun/app.js +++ b/appengine/mailgun/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/mailgun/app.yaml b/appengine/mailgun/app.yaml index f8e942b48c5..233e98927cd 100644 --- a/appengine/mailgun/app.yaml +++ b/appengine/mailgun/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,12 +10,13 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true env_variables: MAILGUN_API_KEY: -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/mailgun/package.json b/appengine/mailgun/package.json index 9b440a1379b..93d55eaab2a 100644 --- a/appengine/mailgun/package.json +++ b/appengine/mailgun/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node app.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "body-parser": "^1.14.1", diff --git a/appengine/mailgun/views/index.jade b/appengine/mailgun/views/index.jade index fce7875b402..8fd8fb94b6f 100644 --- a/appengine/mailgun/views/index.jade +++ b/appengine/mailgun/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/memcached/README.md b/appengine/memcached/README.md new file mode 100644 index 00000000000..e5fe6c1fc18 --- /dev/null +++ b/appengine/memcached/README.md @@ -0,0 +1,9 @@ +# Memcached sample for Google App Engine + +This sample demonstrates accessing Memcached from Node.js on +[Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/memcached/app.js b/appengine/memcached/app.js new file mode 100644 index 00000000000..8cddf8655f5 --- /dev/null +++ b/appengine/memcached/app.js @@ -0,0 +1,49 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); +var Memcached = require('memcached'); + +var app = express(); + +// The environment variables are automatically set by App Engine when running +// on GAE. When running locally, you should have a local instance of the +// memcached daemon running. +var memcachedAddr = process.env.MEMCACHED_PORT_11211_TCP_ADDR || 'localhost'; +var memcachedPort = process.env.MEMCACHED_PORT_11211_TCP_PORT || '11211'; +var memcached = new Memcached(memcachedAddr + ':' + memcachedPort); + +app.get('/', function(req, res, next) { + memcached.get('foo', function(err, value) { + if (err) { return next(err); } + if (value) { + return res.status(200).send('Value: ' + value); + } + + memcached.set('foo', Math.random(), 60, function(err) { + if (err) { return next(err); } + return res.redirect('/'); + }); + }); +}); + +var server = app.listen('8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/memcached/app.yaml b/appengine/memcached/app.yaml new file mode 100644 index 00000000000..c37fa8c3689 --- /dev/null +++ b/appengine/memcached/app.yaml @@ -0,0 +1,25 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START config] +beta_settings: + use_memcache_proxy: true +# [END config] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/memcached/package.json b/appengine/memcached/package.json new file mode 100644 index 00000000000..ce5ff38bd8b --- /dev/null +++ b/appengine/memcached/package.json @@ -0,0 +1,20 @@ +{ + "name": "appengine-memcached", + "description": "Memcached sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "memcached": "^2.2.1" + } +} diff --git a/appengine/mongodb/app.yaml b/appengine/mongodb/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/mongodb/app.yaml +++ b/appengine/mongodb/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/mongodb/package.json b/appengine/mongodb/package.json index 374d36372bd..48458d140ef 100644 --- a/appengine/mongodb/package.json +++ b/appengine/mongodb/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "nconf": "^0.8.0", diff --git a/appengine/mongodb/server.js b/appengine/mongodb/server.js index 6a13cec803c..a05aef04d78 100644 --- a/appengine/mongodb/server.js +++ b/appengine/mongodb/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/pubsub/README.md b/appengine/pubsub/README.md new file mode 100644 index 00000000000..e677d3f306b --- /dev/null +++ b/appengine/pubsub/README.md @@ -0,0 +1,61 @@ +# Node.js Cloud Pub/Sub sample for Google App Engine + +This demonstrates how to send and receive messages using [Google Cloud Pub/Sub](https://cloud.google.com/pubsub) on [Google App Engine Managed VMs](https://cloud.google.com/appengine) using Node.js. + +## Setup + +Before you can run or deploy the sample, you will need to do the following: + +1. Enable the Cloud Pub/Sub API in the [Google Developers Console](https://console.developers.google.com/project/_/apiui/apiview/pubsub/overview). +1. Create a topic and subscription. + + gcloud alpha pubsub topics create + gcloud alpha pubsub subcriptions create \ + --topic \ + --push-endpoint \ + https://.appspot.com/pubsub/push?token= \ + --ack-deadline 30 + +1. Update the environment variables in `app.yaml`. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +When running locally, you can use the [Google Cloud SDK](https://cloud.google.com/sdk) +to provide authentication to use Google Cloud APIs: + + gcloud init + +Then set environment variables before starting your application: + + export GCLOUD_PROJECT= + export PUBSUB_VERIFICATION_TOKEN= + export PUBSUB_TOPIC= + npm start + +### Simulating push notifications + +The application can send messages locally, but it is not able to receive push +messages locally. You can, however, simulate a push message by making an HTTP +request to the local push notification endpoint. There is an included +`sample_message.json`. You can use `curl` or [httpie](https://github.com/jkbrzt/httpie) +to POST this: + + curl -H "Content-Type: application/json" -i --data @sample_message.json ":8080/pubsub/push?token=" + +Or + + http POST ":8080/pubsub/push?token=" < sample_message.json + +Response: + + HTTP/1.1 200 OK + Connection: keep-alive + Date: Mon, 31 Aug 2015 22:19:50 GMT + Transfer-Encoding: chunked + X-Powered-By: Express + +After the request completes, you can refresh `localhost:8080` and see the +message in the list of received messages. diff --git a/appengine/pubsub/app.js b/appengine/pubsub/app.js new file mode 100644 index 00000000000..63ad379d346 --- /dev/null +++ b/appengine/pubsub/app.js @@ -0,0 +1,82 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); +var bodyParser = require('body-parser'); +var gcloud = require('gcloud'); + +var app = express(); +app.set('view engine', 'jade'); + +var formBodyParser = bodyParser.urlencoded({extended: false}); +var jsonBodyParser = bodyParser.json(); + +// List of all messages received by this instance +var messages = []; + +// The following environment variables are set by app.yaml when running on GAE, +// but will need to be manually set when running locally. +var PUBSUB_VERIFICATION_TOKEN = process.env.PUBSUB_VERIFICATION_TOKEN; + +var pubsub = gcloud.pubsub({ + projectId: process.env.GCLOUD_PROJECT || process.env.TEST_PROJECT_ID +}); + +var topic = pubsub.topic(process.env.PUBSUB_TOPIC); + +// [START index] +app.get('/', function(req, res) { + res.render('index', {messages: messages}); +}); + +app.post('/', formBodyParser, function(req, res, next) { + if(!req.body.payload) { + return res.status(400).send('Missing payload'); + } + + topic.publish({ + data: req.body.payload + }, + function(err){ + if(err) { return next(err); } + res.status(200).send('Message sent'); + }); +}); +// [END index] + +// [START push] +app.post('/pubsub/push', jsonBodyParser, function(req, res) { + if(req.query.token !== PUBSUB_VERIFICATION_TOKEN) { + return res.status(400).send(); + } + + // The message is a unicode string encoded in base64. + var message = new Buffer(req.body.message.data, 'base64').toString('utf-8'); + + messages.push(message); + + res.status(200).send(); +}); +// [END push] + +// Start the server +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/pubsub/app.yaml b/appengine/pubsub/app.yaml new file mode 100644 index 00000000000..7100c2f1fc9 --- /dev/null +++ b/appengine/pubsub/app.yaml @@ -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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env] +env_variables: + GCLOUD_PROJECT: + PUBSUB_TOPIC: + # This token is used to verify that requests originate from your + # application. It can be any sufficiently random string. + PUBSUB_VERIFICATION_TOKEN: +# [END env] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/pubsub/package.json b/appengine/pubsub/package.json new file mode 100644 index 00000000000..54a9d0be4a1 --- /dev/null +++ b/appengine/pubsub/package.json @@ -0,0 +1,22 @@ +{ + "name": "appengine-pubsub", + "description": "Node.js Google Cloud PubSub sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "body-parser": "^1.14.2", + "express": "^4.13.3", + "gcloud": "^0.27.0", + "jade": "^1.11.0" + } +} diff --git a/appengine/pubsub/sample_message.json b/appengine/pubsub/sample_message.json new file mode 100644 index 00000000000..8fe62d23fb9 --- /dev/null +++ b/appengine/pubsub/sample_message.json @@ -0,0 +1,5 @@ +{ + "message": { + "data": "SGVsbG8sIFdvcmxkIQ==" + } +} diff --git a/appengine/pubsub/views/index.jade b/appengine/pubsub/views/index.jade new file mode 100644 index 00000000000..ec42f487ef7 --- /dev/null +++ b/appengine/pubsub/views/index.jade @@ -0,0 +1,31 @@ +//- Copyright 2015, 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. + +doctype html +html(lang='en') + head + title PubSub + meta(charset='utf-8') + body + p Messages received by this instance: + ul + each val in messages + li= val + p + small. + Note: because your application is likely running multiple instances, + each instance will have a different list of messages. + + //- [START form] + form(method='post') + textarea(name='payload', placeholder='Enter message here.') + button(type='submit') Send + //- [END form] diff --git a/appengine/redis/app.yaml b/appengine/redis/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/redis/app.yaml +++ b/appengine/redis/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/redis/package.json b/appengine/redis/package.json index e49bb43fea8..9c13b8adaf9 100644 --- a/appengine/redis/package.json +++ b/appengine/redis/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "nconf": "^0.8.0", diff --git a/appengine/redis/server.js b/appengine/redis/server.js index 1d5310f78f0..bbf168c54aa 100644 --- a/appengine/redis/server.js +++ b/appengine/redis/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/restify/app.yaml b/appengine/restify/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/restify/app.yaml +++ b/appengine/restify/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/restify/package.json b/appengine/restify/package.json index d65721e876f..c64ab6acd41 100644 --- a/appengine/restify/package.json +++ b/appengine/restify/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "restify": "^4.0.0" diff --git a/appengine/restify/server.js b/appengine/restify/server.js index f4cbaae3645..d50fe2018fe 100644 --- a/appengine/restify/server.js +++ b/appengine/restify/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/sails/Gruntfile.js b/appengine/sails/Gruntfile.js index 471a7280578..a9bb58959da 100644 --- a/appengine/sails/Gruntfile.js +++ b/appengine/sails/Gruntfile.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/sails/app.js b/appengine/sails/app.js index f2ddaad7303..0b18a6ac3d7 100644 --- a/appengine/sails/app.js +++ b/appengine/sails/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/sails/app.yaml b/appengine/sails/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/sails/app.yaml +++ b/appengine/sails/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/sails/package.json b/appengine/sails/package.json index 5da9a0ed0f7..f756c5f1688 100644 --- a/appengine/sails/package.json +++ b/appengine/sails/package.json @@ -4,13 +4,14 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "debug": "node debug app.js", "start": "node app.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "ejs": "^2.3.4", diff --git a/appengine/sendgrid/README.md b/appengine/sendgrid/README.md index 6f05352763b..486de6b3e56 100644 --- a/appengine/sendgrid/README.md +++ b/appengine/sendgrid/README.md @@ -1,20 +1,33 @@ -## Express.js + Sendgrid on Google App Engine +# Node.js SendGrid email sample for Google App Engine -> [Sendgrid][1]: Delivering your transactional and marketing email through one reliable platform. -> -> – sendgrid.com +This sample demonstrates how to use [SendGrid](https://www.sendgrid.com) on +[Google App Engine Managed VMs](https://cloud.google.com/appengine). -This sample application demonstrates how to use [Express.js][2] and -[sendgrid-nodejs][3] to send transactional email on [Google App Engine][4]. +For more information about SendGrid, see their +[documentation](https://sendgrid.com/docs/User_Guide/index.html). Read the [Sendgrid on App Engine Tutorial][5] for how to run and deploy this sample app. -You can also read the [Sendgrid documentation][6]. +## Setup -[1]: https://sendgrid.com/ -[2]: http://expressjs.com -[3]: https://github.com/sendgrid/sendgrid-nodejs -[4]: https://cloud.google.com/appengine -[5]: https://cloud.google.com/nodejs/resources/tools/sendgrid -[6]: https://sendgrid.com/docs +Before you can run or deploy the sample, you will need to do the following: + +1. [Create a SendGrid Account](http://sendgrid.com/partner/google). As of +September 2015, Google users start with 25,000 free emails per month. +1. Configure your SendGrid settings in the environment variables section in +`app.yaml`. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +You can run the application locally and send emails from your local machine. You +will need to set environment variables before starting your application: + + export SENDGRID_API_KEY= + export SENDGRID_SENDER= + npm start + +[1]: https://cloud.google.com/nodejs/resources/tools/sendgrid diff --git a/appengine/sendgrid/app.js b/appengine/sendgrid/app.js index a0c76878276..7b5a43c5e95 100644 --- a/appengine/sendgrid/app.js +++ b/appengine/sendgrid/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +// [START app] 'use strict'; var express = require('express'); @@ -18,7 +19,11 @@ var path = require('path'); var bodyParser = require('body-parser'); // [START setup] -var Sendgrid = require('sendgrid')(process.env.SENDGRID_API_KEY); +// The following environment variables are set by app.yaml when running on GAE, +// but will need to be manually set when running locally. +var SENDGRID_API_KEY = process.env.SENDGRID_API_KEY; +var SENDGRID_SENDER = process.env.SENDGRID_SENDER; +var Sendgrid = require('sendgrid')(SENDGRID_API_KEY); // [END setup] var app = express(); @@ -39,7 +44,7 @@ app.get('/', function(req, res) { // [START hello] app.post('/hello', function(req, res, next) { Sendgrid.send({ - from: 'no-reply@appengine-sendgrid-demo.com', // From address + from: SENDGRID_SENDER, // From address to: req.body.email, // To address subject: 'Hello World!', // Subject text: 'Sendgrid on Google App Engine with Node.js', // Content @@ -71,3 +76,4 @@ if (module === require.main) { } module.exports = app; +// [END app] diff --git a/appengine/sendgrid/app.yaml b/appengine/sendgrid/app.yaml index b67a0dc2c01..bce63b7e9d3 100644 --- a/appengine/sendgrid/app.yaml +++ b/appengine/sendgrid/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,12 +10,17 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true + +# [START env_variables] env_variables: SENDGRID_API_KEY: -# [END app_yaml] + SENDGRID_SENDER: +# [END env_variables] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/sendgrid/package.json b/appengine/sendgrid/package.json index 29a43e7a50c..145a2f06761 100644 --- a/appengine/sendgrid/package.json +++ b/appengine/sendgrid/package.json @@ -4,12 +4,13 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, "scripts": { "start": "node app.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "body-parser": "^1.14.1", diff --git a/appengine/sendgrid/views/index.jade b/appengine/sendgrid/views/index.jade index bfa6d827121..b26209426d5 100644 --- a/appengine/sendgrid/views/index.jade +++ b/appengine/sendgrid/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/static-files/README.md b/appengine/static-files/README.md new file mode 100644 index 00000000000..bd60667d227 --- /dev/null +++ b/appengine/static-files/README.md @@ -0,0 +1,8 @@ +# Serving static files in Node.js sample for Google App Engine + +This sample demonstrates serving static files in a Node.js app for [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. diff --git a/appengine/static-files/app.js b/appengine/static-files/app.js new file mode 100644 index 00000000000..41db1a82236 --- /dev/null +++ b/appengine/static-files/app.js @@ -0,0 +1,36 @@ +// 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. + +// [START app] +'use strict'; + +var express = require('express'); +var app = express(); + +app.set('view engine', 'jade'); + +// Use the built-in express middleware for serving static files from './public' +app.use('/static', express.static('public')); + +app.get('/', function(req, res) { + res.render('index'); +}); + +// Start the server +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/static-files/app.yaml b/appengine/static-files/app.yaml new file mode 100644 index 00000000000..4748785677f --- /dev/null +++ b/appengine/static-files/app.yaml @@ -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. + +# [START app_yaml] +runtime: nodejs +vm: true + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/static-files/package.json b/appengine/static-files/package.json new file mode 100644 index 00000000000..da06b8c9b00 --- /dev/null +++ b/appengine/static-files/package.json @@ -0,0 +1,20 @@ +{ + "name": "appengine-static-files", + "description": "Serving static files in Node.js sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "jade": "^1.11.0" + } +} diff --git a/appengine/static-files/public/main.css b/appengine/static-files/public/main.css new file mode 100644 index 00000000000..478845edb6d --- /dev/null +++ b/appengine/static-files/public/main.css @@ -0,0 +1,21 @@ +/* +Copyright 2015 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. +*/ +/* [START example] */ +body { + font-family: Verdana, Helvetica, sans-serif; + background-color: #CCCCFF; +} +/* [END example] */ diff --git a/appengine/static-files/views/index.jade b/appengine/static-files/views/index.jade new file mode 100644 index 00000000000..5d27e8e4154 --- /dev/null +++ b/appengine/static-files/views/index.jade @@ -0,0 +1,19 @@ +//- Copyright 2015, 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. + +doctype html +html(lang="en") + head + title Static Files + meta(charset='utf-8') + link(rel="stylesheet", href="/static/main.css") + body + p This is a static file serving example. diff --git a/appengine/storage/README.md b/appengine/storage/README.md new file mode 100644 index 00000000000..7cb0f58bd06 --- /dev/null +++ b/appengine/storage/README.md @@ -0,0 +1,40 @@ +# Node.js Google Cloud Storage sample for Google App Engine + +This sample demonstrates how to use [Google Cloud Storage](https://cloud.google.com/storage/) +on [Google App Engine Managed VMs](https://cloud.google.com/appengine). + +## Setup + +Before you can run or deploy the sample, you will need to do the following: + +1. Enable the Cloud Storage API in the [Google Developers Console](https://console.developers.google.com/project/_/apiui/apiview/storage/overview). + +1. Create a Cloud Storage Bucket. You can do this with the [Google Cloud SDK](https://cloud.google.com/sdk) +with the following command: + + gsutil mb gs:// + +1. Set the default ACL on your bucket to public read in order to serve files +directly from Cloud Storage. You can do this with the [Google Cloud SDK](https://cloud.google.com/sdk) +with the following command: + + gsutil defacl set public-read gs:// + +1. Update the environment variables in `app.yaml`. + +## Running locally + +Refer to the [top-level README](../README.md) for instructions on running and +deploying. + +When running locally, you can use the [Google Cloud SDK](https://cloud.google.com/sdk) +to provide authentication to use Google Cloud APIs: + + gcloud init + +Then set environment variables before starting your application: + + export GCLOUD_PROJECT= + export GCLOUD_STORAGE_BUCKET= + npm install + npm start diff --git a/appengine/storage/app.js b/appengine/storage/app.js new file mode 100644 index 00000000000..636e4619ec3 --- /dev/null +++ b/appengine/storage/app.js @@ -0,0 +1,83 @@ +// 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. + +// [START app] +'use strict'; + +var format = require('util').format; +var express = require('express'); +var gcloud = require('gcloud'); + +var app = express(); +app.set('view engine', 'jade'); + +// [START config] +// Multer is required to process file uploads and make them available via +// req.files. +var multer = require('multer')({ + inMemory: true, + fileSize: 5 * 1024 * 1024 // no larger than 5mb, you can change as needed. +}); + +// The following environment variables are set by app.yaml when running on GAE, +// but will need to be manually set when running locally. +// The storage client is used to communicate with Google Cloud Storage +var storage = gcloud.storage({ + projectId: process.env.GCLOUD_PROJECT || process.env.TEST_PROJECT_ID +}); + +// A bucket is a container for objects (files). +var bucket = storage.bucket(process.env.GCLOUD_STORAGE_BUCKET); +// [END config] + +// [START form] +// Display a form for uploading files. +app.get('/', function(req, res) { + res.render('form.jade'); +}); +// [END form] + +// [START process] +// Process the file upload and upload to Google Cloud Storage. +app.post('/upload', multer.single('file'), function(req, res, next) { + if (!req.file) { + return res.status(400).send('No file uploaded.'); + } + + // Create a new blob in the bucket and upload the file data. + var blob = bucket.file(req.file.originalname); + var blobStream = blob.createWriteStream(); + + blobStream.on('error', function(err) { + return next(err); + }); + + blobStream.on('finish', function() { + // The public URL can be used to directly access the file via HTTP. + var publicUrl = format( + 'https://storage.googleapis.com/%s/%s', + bucket.name, blob.name); + res.status(200).send(publicUrl); + }); + + blobStream.end(req.file.buffer); +}); +// [END process] + +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/storage/app.yaml b/appengine/storage/app.yaml new file mode 100644 index 00000000000..373ff966f45 --- /dev/null +++ b/appengine/storage/app.yaml @@ -0,0 +1,26 @@ +# 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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env] +env_variables: + GCLOUD_PROJECT: + GCLOUD_STORAGE_BUCKET: +# [END env] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/storage/package.json b/appengine/storage/package.json new file mode 100644 index 00000000000..e340a663754 --- /dev/null +++ b/appengine/storage/package.json @@ -0,0 +1,16 @@ +{ + "name": "appengine-storage", + "description": "Node.js Google Cloud Storage sample for Google App Engine", + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "body-parser": "^1.14.2", + "express": "^4.13.3", + "gcloud": "^0.27.0", + "jade": "^1.11.0", + "multer": "^1.1.0" + } +} diff --git a/appengine/storage/views/form.jade b/appengine/storage/views/form.jade new file mode 100644 index 00000000000..55ac0359b3c --- /dev/null +++ b/appengine/storage/views/form.jade @@ -0,0 +1,21 @@ +//- Copyright 2015, 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. + +doctype html +html(lang="en") + head + title Static Files + meta(charset='utf-8') + link(rel="stylesheet", href="/static/main.css") + body + form(method="POST", action="/upload", enctype="multipart/form-data") + input(type="file", name="file") + input(type="submit") diff --git a/appengine/twilio/README.md b/appengine/twilio/README.md new file mode 100644 index 00000000000..493b99a8777 --- /dev/null +++ b/appengine/twilio/README.md @@ -0,0 +1,35 @@ +# Node.js Twilio voice and SMS sample for Google App Engine + +This sample demonstrates how to use [Twilio](https://www.twilio.com) on +[Google App Engine Managed VMs](https://cloud.google.com/appengine). + +For more information about Twilio, see the +[Twilio Node library](https://www.twilio.com/docs/node/install). + +## Setup + +Before you can run or deploy the sample, you will need to do the following: + +1. [Create a Twilio Account](http://ahoy.twilio.com/googlecloudplatform). Google +App Engine customers receive a complimentary credit for SMS messages and inbound +messages. + +1. Create a number on twilio, and configure the voice request URL to be +`https://.appspot.com/call/receive` and the SMS request URL to +be `https://.appspot.com/sms/receive`. + +1. Configure your Twilio settings in the environment variables section in +`app.yaml`. + +## Running locally + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +You can run the application locally to test the callbacks and SMS sending. You +will need to set environment variables before starting your application: + + export TWILIO_ACCOUNT_SID= + export TWILIO_AUTH_TOKEN= + export TWILIO_NUMBER= + npm start diff --git a/appengine/twilio/app.js b/appengine/twilio/app.js new file mode 100644 index 00000000000..0c72e6abfc3 --- /dev/null +++ b/appengine/twilio/app.js @@ -0,0 +1,91 @@ +// 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. + +// [START app] +'use strict'; + +var format = require('util').format; +var express = require('express'); +var bodyParser = require('body-parser').urlencoded({ + extended: false +}); + +var app = express(); + +// [START config] +var TWILIO_NUMBER = process.env.TWILIO_NUMBER; +if (!TWILIO_NUMBER) { + console.log( + 'Please configure environment variables as described in README.md'); + process.exit(1); +} + +var twilio = require('twilio')( + process.env.TWILIO_ACCOUNT_SID, + process.env.TWILIO_AUTH_TOKEN); + +var TwimlResponse = require('twilio').TwimlResponse; +// [END config] + +// [START receive_call] +app.post('/call/receive', function(req, res) { + var resp = new TwimlResponse(); + resp.say('Hello from Google App Engine.'); + + res.status(200) + .contentType('text/xml') + .send(resp.toString()); +}); +// [END receive_call] + +// [START send_sms] +app.get('/sms/send', function(req, res, next) { + var to = req.query.to; + if (!to) { + return res.status(400).send( + 'Please provide an number in the "to" query string parameter.'); + } + + twilio.sendMessage({ + to: to, + from: TWILIO_NUMBER, + body: 'Hello from Google App Engine' + }, function(err) { + if (err) { return next(err); } + res.status(200).send('Message sent.'); + }); +}); +// [END send_sms] + +// [START receive_sms] +app.post('/sms/receive', bodyParser, function(req, res) { + var sender = req.body.From; + var body = req.body.Body; + + var resp = new TwimlResponse(); + resp.message(format('Hello, %s, you said: %s', sender, body)); + + res.status(200) + .contentType('text/xml') + .send(resp.toString()); +}); +// [END receive_sms] + +// Start the server +var server = app.listen(process.env.PORT || '8080', '0.0.0.0', function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); +}); +// [END app] diff --git a/appengine/twilio/app.yaml b/appengine/twilio/app.yaml new file mode 100644 index 00000000000..8727f06992d --- /dev/null +++ b/appengine/twilio/app.yaml @@ -0,0 +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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START env_variables] +env_variables: + TWILIO_ACCOUNT_SID: + TWILIO_AUTH_TOKEN: + TWILIO_NUMBER: +# [END env_variables] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/twilio/package.json b/appengine/twilio/package.json new file mode 100644 index 00000000000..a69a415d239 --- /dev/null +++ b/appengine/twilio/package.json @@ -0,0 +1,21 @@ +{ + "name": "appengine-twilio", + "description": "Samples for Google App Engine Managed VMs", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "body-parser": "^1.14.2", + "express": "^4.13.3", + "twilio": "^2.8.0" + } +} diff --git a/appengine/webpack/app.yaml b/appengine/webpack/app.yaml index e795035a8b1..4748785677f 100644 --- a/appengine/webpack/app.yaml +++ b/appengine/webpack/app.yaml @@ -1,4 +1,4 @@ -# Copyright 2015, Google, Inc. +# 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 @@ -10,10 +10,11 @@ # 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. -# + # [START app_yaml] runtime: nodejs vm: true -# [END app_yaml] + skip_files: - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/webpack/package.json b/appengine/webpack/package.json index 97fc5233687..281fd8138f1 100644 --- a/appengine/webpack/package.json +++ b/appengine/webpack/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": "~4.2" }, @@ -11,7 +12,7 @@ "bundle": "webpack --config webpack.config.js", "prestart": "npm run bundle", "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml" + "deploy": "gcloud preview app deploy" }, "dependencies": { "express": "^4.13.3", diff --git a/appengine/webpack/public/app.js b/appengine/webpack/public/app.js index a4a46114e86..74d67f629df 100644 --- a/appengine/webpack/public/app.js +++ b/appengine/webpack/public/app.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/webpack/public/foo.js b/appengine/webpack/public/foo.js index 884eb957d5b..9f7797f3ca5 100644 --- a/appengine/webpack/public/foo.js +++ b/appengine/webpack/public/foo.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/webpack/server.js b/appengine/webpack/server.js index 85f252f3201..bca556205bc 100644 --- a/appengine/webpack/server.js +++ b/appengine/webpack/server.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/webpack/views/index.jade b/appengine/webpack/views/index.jade index 28bbeec963a..afe188825b4 100644 --- a/appengine/webpack/views/index.jade +++ b/appengine/webpack/views/index.jade @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/webpack/webpack.config.js b/appengine/webpack/webpack.config.js index 4ce719f1847..119c29c3fb3 100644 --- a/appengine/webpack/webpack.config.js +++ b/appengine/webpack/webpack.config.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/appengine/websockets/README.md b/appengine/websockets/README.md new file mode 100644 index 00000000000..9d537714ad7 --- /dev/null +++ b/appengine/websockets/README.md @@ -0,0 +1,25 @@ +# Node.js websockets sample for Google App Engine + +This sample demonstrates how to use websockets on +[Google App Engine Managed VMs](https://cloud.google.com/appengine) with Node.js. + +__Note:__ Secure WebSockets are currently not supported by Managed VMs. +WebSockets will only work if you load your page over HTTP (not HTTPS). + +To use Secure WebSockets now, you can launch a VM on Google Compute Engine using +a custom image where you have added SSL support for WebSockets. + +Refer to the [appengine/README.md](../README.md) file for instructions on +running and deploying. + +## Setup + +Before you can run or deploy the sample, you will need to create a new firewall +rule to allow traffic on port 65080. This port will be used for websocket +connections. You can do this with the +[Google Cloud SDK](https://cloud.google.com/sdk) with the following command: + + gcloud compute firewall-rules create default-allow-websockets \ + --allow tcp:65080 \ + --target-tags websocket \ + --description "Allow websocket traffic on port 65080" diff --git a/appengine/websockets/app.js b/appengine/websockets/app.js new file mode 100644 index 00000000000..f3584a7e359 --- /dev/null +++ b/appengine/websockets/app.js @@ -0,0 +1,89 @@ +// 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. + +// [START app] +'use strict'; + +var http = require('http'); +var express = require('express'); +var request = require('request'); + +var app = express(); +app.set('view engine', 'jade'); + +// Use express-ws to enable web sockets. +require('express-ws')(app); + +// A simple echo service. +app.ws('/echo', function(ws) { + ws.on('message', function(msg) { + ws.send(msg); + }); +}); + +app.get('/', function(req, res) { + getExternalIp(function(externalIp){ + res.render('index.jade', {externalIp: externalIp}); + }); +}); + +// [START external_ip] +// In order to use websockets on App Engine, you need to connect directly to +// application instance using the instance's public external IP. This IP can +// be obtained from the metadata server. +var METADATA_NETWORK_INTERFACE_URL = 'http://metadata/computeMetadata/v1/' + + '/instance/network-interfaces/0/access-configs/0/external-ip'; + +function getExternalIp(cb) { + var options = { + url: METADATA_NETWORK_INTERFACE_URL, + headers: { + 'Metadata-Flavor': 'Google' + } + }; + + request(options, function(err, resp, body){ + if(err || resp.statusCode !== 200) { + console.log('Error while talking to metadata server, assuming localhost'); + return cb('localhost'); + } + return cb(body); + }); +} +// [END external_ip] + +// Start the websocket server +var wsServer = app.listen( + '65080', + '0.0.0.0', + function() { + console.log('Websocket server listening at http://%s:%s', + wsServer.address().address, + wsServer.address().port); + } +); + +// Additionally listen for non-websocket connections on the default App Engine +// port 8080. Using http.createServer will skip express-ws's logic to upgrade +// websocket connections. +var server = http.createServer(app).listen( + process.env.PORT || '8080', + '0.0.0.0', + function() { + console.log('App listening at http://%s:%s', server.address().address, + server.address().port); + console.log('Press Ctrl+C to quit.'); + } +); +// [END app] diff --git a/appengine/websockets/app.yaml b/appengine/websockets/app.yaml new file mode 100644 index 00000000000..57011164759 --- /dev/null +++ b/appengine/websockets/app.yaml @@ -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. + +# [START app_yaml] +runtime: nodejs +vm: true + +# [START network] +# This ensures clients will be able to connect via websockets to any instance of +# this app using websockets +network: + forwarded_ports: + - 65080 + instance_tag: websocket +# [END network] + +skip_files: + - ^(.*/)?.*/node_modules/.*$ +# [END app_yaml] diff --git a/appengine/websockets/package.json b/appengine/websockets/package.json new file mode 100644 index 00000000000..3325aacad48 --- /dev/null +++ b/appengine/websockets/package.json @@ -0,0 +1,22 @@ +{ + "name": "appengine-websockets", + "description": "Node.js websockets sample for Google App Engine", + "version": "0.0.1", + "private": true, + "license": "Apache Version 2.0", + "author": "Google Inc.", + "engines": { + "node": "~4.2" + }, + "scripts": { + "start": "node app.js", + "monitor": "nodemon app.js", + "deploy": "gcloud preview app deploy" + }, + "dependencies": { + "express": "^4.13.3", + "express-ws": "^1.0.0-rc.2", + "jade": "^1.11.0", + "request": "^2.67.0" + } +} diff --git a/appengine/websockets/views/index.jade b/appengine/websockets/views/index.jade new file mode 100644 index 00000000000..fd3d0b46eb9 --- /dev/null +++ b/appengine/websockets/views/index.jade @@ -0,0 +1,81 @@ +//- 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. + +doctype html +html(lang="en") + head + title Websockets Echo + meta(charset="utf-8") + //- [START form] + body(data-external-ip=externalIp) + p Echo demo + form(id="echo-form") + textarea(id="echo-text", placeholder="Enter some text...") + button(type="submit") Send + + div + p Response: + pre(id="echo-response") + + div + p Status: + pre(id="echo-status") + //- [END form] + + script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js") + script. + // [START js] + $(function() { + /* The external ip is determined by main.py and passed into the template. */ + var webSocketHost = location.protocol === 'https:' ? 'wss://' : 'ws://'; + var externalIp = $('body').data('external-ip'); + var webSocketUri = webSocketHost + externalIp + ':65080/echo'; + + /* Get elements from the page */ + var form = $('#echo-form'); + var textarea = $('#echo-text'); + var output = $('#echo-response'); + var status = $('#echo-status'); + + /* Helper to keep an activity log on the page. */ + function log(text){ + status.text(status.text() + text + '\n'); + } + + /* Establish the WebSocket connection and register event handlers. */ + var websocket = new WebSocket(webSocketUri); + + websocket.onopen = function() { + log('Connected'); + }; + + websocket.onclose = function() { + log('Closed'); + }; + + websocket.onmessage = function(e) { + log('Message received'); + output.text(e.data); + }; + + websocket.onerror = function(e) { + log('Error (see console)'); + console.log(e); + }; + + /* Handle form submission and send a message to the websocket. */ + form.submit(function(e) { + e.preventDefault(); + var data = textarea.val(); + websocket.send(data); + }); + }); + // [END js] diff --git a/computeengine/sendgrid/package.json b/computeengine/sendgrid/package.json index e22e34f062c..0b8e86679f8 100644 --- a/computeengine/sendgrid/package.json +++ b/computeengine/sendgrid/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": ">=0.10.x" }, diff --git a/computeengine/sendgrid/sendmail.js b/computeengine/sendgrid/sendmail.js index 08826079b2b..37176d881d1 100644 --- a/computeengine/sendgrid/sendmail.js +++ b/computeengine/sendgrid/sendmail.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/datastore/package.json b/datastore/package.json index 05a3dc762a5..1c99ffb7837 100644 --- a/datastore/package.json +++ b/datastore/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": ">=0.10.x" }, diff --git a/datastore/tasks.js b/datastore/tasks.js index 7d2c6f713c4..dce6b23de82 100755 --- a/datastore/tasks.js +++ b/datastore/tasks.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/logging/package.json b/logging/package.json index 340a02a9315..bb512293083 100644 --- a/logging/package.json +++ b/logging/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": ">=0.10.x" }, diff --git a/package.json b/package.json index 01b768454c1..5e5c9bccf9f 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,10 @@ { "name": "Jason Dobry", "email": "jason.dobry@gmail.com" + }, + { + "name": "Jon Wayne Parrott", + "email": "jonwayne@google.com" } ], "repository": { @@ -24,15 +28,15 @@ "mocha": "mocha --timeout 10000 --recursive", "cover": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- --timeout 10000 --recursive", "coveralls": "cat ./coverage/lcov.info | node_modules/.bin/coveralls", - "deps_datastore": "cd datastore && 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_express": "cd appengine/express && npm i && cd ../..", - "deps_sendgrid": "cd appengine/sendgrid && npm i && cd ../.. && cd computeengine/sendgrid && npm i && cd ../..", + "deps_datastore": "cd datastore; 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_express": "cd appengine/express; npm i; cd ../..", + "deps_sendgrid": "cd appengine/sendgrid; npm i; cd ../..; cd computeengine/sendgrid; npm i; cd ../..", "deps_memcached": "cd appengine/express-memcached-session && 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_prediction && npm run deps_logging && npm run deps_memcached && npm run deps_express && npm run deps_sendgrid && npm run pretest_geddy", + "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_prediction; npm run deps_logging; npm run deps_memcached; npm run deps_express; npm run deps_sendgrid; npm run pretest_geddy", "test": "npm run jshint && npm run cover" }, "devDependencies": { diff --git a/prediction/package.json b/prediction/package.json index c9d1df34d7d..b8d38bf03e4 100644 --- a/prediction/package.json +++ b/prediction/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": ">=0.10.x" }, diff --git a/storage/authSample.js b/storage/authSample.js index 42f537ee5c5..5952edf59c7 100644 --- a/storage/authSample.js +++ b/storage/authSample.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/storage/package.json b/storage/package.json index 073802d7ee0..0326c705f07 100644 --- a/storage/package.json +++ b/storage/package.json @@ -4,6 +4,7 @@ "version": "0.0.1", "private": true, "license": "Apache Version 2.0", + "author": "Google Inc.", "engines": { "node": ">=0.10.x" }, diff --git a/test/appengine/all.test.js b/test/appengine/all.test.js index 182f7566707..df3f88b4071 100644 --- a/test/appengine/all.test.js +++ b/test/appengine/all.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 @@ -24,13 +24,45 @@ function getPath(dir) { return cwd + '/appengine/' + dir; } +function changeScaling(dir) { + try { + var filepath = getPath(dir) + '/app.yaml'; + fs.statSync(filepath); + + var appYaml = fs.readFileSync(filepath, { encoding: 'utf8' }); + + appYaml = appYaml + '\n\nmanual_scaling:\n instances: 1\n'; + fs.writeFileSync(filepath, appYaml, { encoding: 'utf8' }); + } catch (err) { + console.error(err); + } +} + var sampleTests = [ + { + dir: 'analytics', + cmd: 'node', + args: ['app.js'], + msg: 'Event tracked.' + }, { dir: 'bower', cmd: 'node', args: ['server.js'], msg: 'Using jquery, installed via Bower.' }, + { + dir: 'datastore', + cmd: 'node', + args: ['app.js'], + msg: 'Last 10 visits:' + }, + { + dir: 'disk', + cmd: 'node', + args: ['app.js'], + msg: 'Instance:' + }, { dir: 'express', deploy: true, @@ -67,6 +99,12 @@ var sampleTests = [ args: ['index.js'], msg: 'Hello World! Hapi.js on Google App Engine.' }, + { + dir: 'hello-world', + cmd: 'node', + args: ['app.js'], + msg: 'Hello, world!' + }, { dir: 'kraken', cmd: 'node', @@ -74,6 +112,12 @@ var sampleTests = [ msg: 'Hello World! Kraken.js on Google App Engine.', code: 304 }, + { + dir: 'logging', + cmd: 'node', + args: ['app.js'], + msg: 'Logged' + }, { dir: 'loopback', cmd: 'node', @@ -87,6 +131,23 @@ var sampleTests = [ args: ['app.js'], msg: 'Express.js + Mailgun on Google App Engine.' }, + { + dir: 'memcached', + cmd: 'node', + args: ['app.js'], + msg: 'Value:', + test: /Value: \d\.\d+/ + }, + { + dir: 'pubsub', + cmd: 'node', + args: ['app.js'], + msg: 'Messages received by this instance:', + env: { + PUBSUB_TOPIC: 'test', + PUBSUB_VERIFICATION_TOKEN: 'foo' + } + }, { dir: 'redis', cmd: 'node', @@ -105,11 +166,32 @@ var sampleTests = [ args: ['app.js'], msg: 'Express.js + Sendgrid on Google App Engine.' }, + { + dir: 'static-files', + cmd: 'node', + args: ['app.js'], + msg: 'This is a static file serving example.' + }, + { + dir: 'storage', + cmd: 'node', + args: ['app.js'], + msg: 'Static Files', + env: { + GCLOUD_STORAGE_BUCKET: 'nodejs-docs-samples' + } + }, { dir: 'webpack', cmd: 'node', args: ['server.js'], msg: 'Loaded module foo via Webpack.' + }, + { + dir: 'websockets', + cmd: 'node', + args: ['app.js'], + msg: 'Echo demo' } ]; @@ -147,7 +229,8 @@ function testRequest(url, sample, cb) { return cb(err); } else { if (body && body.indexOf(sample.msg) !== -1 && - (res.statusCode === 200 || res.statusCode === sample.code)) { + (res.statusCode === 200 || res.statusCode === sample.code) && + (!sample.test || sample.test.test(body))) { // Success return cb(null, true); } else { @@ -226,9 +309,18 @@ function testInstallation(sample, done) { function testLocalApp(sample, done) { var calledDone = false; - var proc = spawn(sample.cmd, sample.args, { + var opts = { cwd: getPath(sample.dir) - }); + }; + if (sample.env) { + opts.env = sample.env; + for (var key in process.env) { + if (process.env.hasOwnProperty(key)) { + opts.env[key] = process.env[key]; + } + } + } + var proc = spawn(sample.cmd, sample.args, opts); proc.on('error', finish); @@ -282,6 +374,9 @@ function testDeployments(done) { // Keep track off whether the logs have fully flushed var logFinished = false; + // Manually set # of instances to 1 + changeScaling(sample.dir); + var _cwd = getPath(sample.dir); var args = [ 'preview', diff --git a/test/appengine/express-memcached-session.test.js b/test/appengine/express-memcached-session.test.js index 6508023084b..dbfc1040ae9 100644 --- a/test/appengine/express-memcached-session.test.js +++ b/test/appengine/express-memcached-session.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/test/appengine/express.test.js b/test/appengine/express.test.js index a05b545413d..dbea5c4c330 100644 --- a/test/appengine/express.test.js +++ b/test/appengine/express.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/test/appengine/sendgrid.test.js b/test/appengine/sendgrid.test.js index 1ea56065d9e..c00ceb86e4b 100644 --- a/test/appengine/sendgrid.test.js +++ b/test/appengine/sendgrid.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/test/computeengine/sendgrid.test.js b/test/computeengine/sendgrid.test.js index 545d9c3f435..d4c7bae861f 100644 --- a/test/computeengine/sendgrid.test.js +++ b/test/computeengine/sendgrid.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/test/datastore/tasks.test.js b/test/datastore/tasks.test.js index 9880dfe0965..4b72bf9fb56 100644 --- a/test/datastore/tasks.test.js +++ b/test/datastore/tasks.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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 diff --git a/test/storage/authSample.test.js b/test/storage/authSample.test.js index ac10d8081a8..51527cf1e0a 100644 --- a/test/storage/authSample.test.js +++ b/test/storage/authSample.test.js @@ -1,4 +1,4 @@ -// Copyright 2015, Google, Inc. +// 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