Skip to content

Commit e83f4c1

Browse files
authored
Split Cloud SQL sample into two samples. (#481)
1 parent 79dc773 commit e83f4c1

File tree

15 files changed

+607
-304
lines changed

15 files changed

+607
-304
lines changed

appengine/cloudsql/README.md

Lines changed: 5 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,11 @@
1-
# Node.js Cloud SQL sample on Google App Engine
1+
# Cloud SQL for MySQL Node.js sample on App Engine flexible environment
22

3-
This sample demonstrates how to use [Google Cloud SQL][sql] (or any other SQL
4-
server) on [Google App Engine Flexible][flexible].
3+
This sample demonstrates how to use [Google Cloud SQL][sql] for
4+
[MySQL][mysql] on [Google App Engine Flexible][flexible].
55

6-
This sample has instructions for both [MySQL][mysql] and [Postgres][postgres].
7-
8-
## Setup
9-
10-
### General steps
11-
Before you can run or deploy the sample, you will need to do the following:
12-
13-
1. In order for some of the commands below to work, you need to enable the
14-
[Cloud SQL Admin API](https://console.cloud.google.com/apis/api/sqladmin-json.googleapis.com/overview).
15-
1. Create a [Second Generation Cloud SQL][gen] instance. You can do this from
16-
the [Cloud Console][console] or via the [Cloud SDK][sdk]. To create it via the
17-
SDK use the following command:
18-
19-
gcloud sql instances create [YOUR_INSTANCE_NAME] \
20-
--activation-policy=ALWAYS \
21-
--tier=db-n1-standard-1
22-
23-
where `[YOUR_INSTANCE_NAME]` is a name of your choice.
24-
25-
1. Set the root password on your Cloud SQL instance:
26-
27-
gcloud sql instances set-root-password [YOUR_INSTANCE_NAME] --password [YOUR_INSTANCE_ROOT_PASSWORD]
28-
29-
where `[YOUR_INSTANCE_NAME]` is the name you chose in step 1 and
30-
`[YOUR_INSTANCE_ROOT_PASSWORD]` is a password of your choice.
31-
32-
1. Using the [Cloud SQL console][sql_console], select your Cloud SQL instance.
33-
Then, create a [user][user] (using the button in the *Access Control* > *Users* tab) and a
34-
[database][database] (using the button in the *Databases* tab).
35-
36-
1. Create and download a [Service Account][service] for your project. You will
37-
use this service account to connect to your Cloud SQL instance locally.
38-
39-
1. Download and install the [Cloud SQL Proxy][proxy].
40-
41-
1. [Start the proxy][start] to allow connecting to your instance from your local
42-
machine:
43-
44-
./cloud_sql_proxy \
45-
-instances=[YOUR_INSTANCE_CONNECTION_NAME]=tcp:[PORT] \
46-
-credential_file=PATH_TO_YOUR_SERVICE_ACCOUNT_JSON_FILE
47-
48-
where `[YOUR_INSTANCE_CONNECTION_NAME]` is the connection name of your
49-
instance on its Overview page in the Google Cloud Platform Console, or use
50-
`[YOUR_PROJECT_ID]:[YOUR_REGION]:[YOUR_INSTANCE_NAME]`. If you're using
51-
MySQL, `[PORT]` will be `3306`; for Postgres, it will be `5432`.
52-
53-
1. In a separate terminal, set the `SQL_USER`, `SQL_PASSWORD`, and `SQL_DATABASE` environment
54-
variables to their respective values. This allows your local app to connect to your Cloud SQL
55-
instance through the proxy.
56-
57-
export SQL_USER="..."
58-
export SQL_PASSWORD="..."
59-
export SQL_DATABASE="..."
60-
61-
### Choosing a SQL client
62-
Choose which database connector to use via the `SQL_CLIENT` environment variable.
63-
64-
To use MySQL, set it to `mysql`:
65-
66-
export SQL_CLIENT="mysql"
67-
68-
To use Postgres, set it to `pg`:
69-
70-
export SQL_CLIENT="pg"
71-
72-
### Final setup steps
73-
1. Update the values in `app.yaml` with your instance configuration.
74-
75-
1. Finally, run `createTables.js` to ensure that the database is properly
76-
configured and to create the tables needed for the sample.
77-
78-
### Running locally
79-
80-
Refer to the [top-level README](../README.md) for instructions on running and deploying.
81-
82-
It's recommended to follow the instructions above to run the Cloud SQL proxy.
83-
You will need to set the appropriate environment variables (as shown above) and
84-
run the following commands via your shell to run the sample:
85-
86-
npm install
87-
npm start
6+
To run the sample, see [the tutorial][tutorial].
887

898
[sql]: https://cloud.google.com/sql/
909
[flexible]: https://cloud.google.com/appengine
91-
[gen]: https://cloud.google.com/sql/docs/create-instance
92-
[console]: https://console.developers.google.com
93-
[sql_console]: https://console.developers.google.com/sql/instances/
94-
[sdk]: https://cloud.google.com/sdk
95-
[service]: https://cloud.google.com/sql/docs/external#createServiceAccount
96-
[proxy]: https://cloud.google.com/sql/docs/external#install
97-
[start]: https://cloud.google.com/sql/docs/external#6_start_the_proxy
98-
[user]: https://cloud.google.com/sql/docs/create-user
99-
[database]: https://cloud.google.com/sql/docs/create-database
10010
[mysql]: https://www.mysql.com/downloads/
101-
[postgres]: https://www.postgresql.org/download/
11+
[tutorial]: https://cloud.google.com/appengine/docs/flexible/nodejs/using-cloud-sql

appengine/cloudsql/app.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ env: flex
1717

1818
# [START env]
1919
env_variables:
20-
SQL_USER: YOUR_USER
21-
SQL_PASSWORD: YOUR_PASSWORD
22-
SQL_DATABASE: YOUR_DATABASE
20+
SQL_USER: YOUR_SQL_USER
21+
SQL_PASSWORD: YOUR_SQL_PASSWORD
22+
SQL_DATABASE: YOUR_SQL_DATABASE
2323
# e.g. my-awesome-project:us-central1:my-cloud-sql-instance
2424
INSTANCE_CONNECTION_NAME: YOUR_INSTANCE_CONNECTION_NAME
25-
SQL_CLIENT: YOUR_SQL_CLIENT # either 'pg' or 'mysql' (all lowercase)
2625
# [END env]
2726

2827
# [START cloudsql_settings]

appengine/cloudsql/createTables.js

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,84 +15,39 @@
1515

1616
'use strict';
1717

18-
// Require process, so we can mock environment variables
19-
const process = require('process');
20-
2118
// [START createTables]
22-
// [START setup]
2319
const Knex = require('knex');
2420
const prompt = require('prompt');
25-
// [END setup]
2621

27-
// [START createTable]
28-
/**
29-
* Create the "visits" table.
30-
*
31-
* @param {object} knex A Knex client object.
32-
*/
33-
function createTable (knex) {
34-
return knex.schema.createTable('visits', (table) => {
22+
const FIELDS = ['user', 'password', 'database'];
23+
24+
prompt.start();
25+
26+
// Prompt the user for connection details
27+
prompt.get(FIELDS, (err, config) => {
28+
if (err) {
29+
console.error(err);
30+
return;
31+
}
32+
33+
// Connect to the database
34+
const knex = Knex({ client: 'mysql', connection: config });
35+
36+
// Create the "visits" table
37+
knex.schema.createTable('visits', (table) => {
3538
table.increments();
3639
table.timestamp('timestamp');
3740
table.string('userIp');
3841
})
3942
.then(() => {
4043
console.log(`Successfully created 'visits' table.`);
41-
return knex;
44+
return knex.destroy();
4245
})
4346
.catch((err) => {
4447
console.error(`Failed to create 'visits' table:`, err);
45-
return knex;
48+
if (knex) {
49+
knex.destroy();
50+
}
4651
});
47-
}
48-
// [END createTable]
49-
50-
// [START getConnection]
51-
/**
52-
* Ask the user for connection configuration and create a new connection.
53-
*/
54-
function getConnection () {
55-
const FIELDS = ['user', 'password', 'database'];
56-
return new Promise((resolve, reject) => {
57-
prompt.start();
58-
prompt.get(FIELDS, (err, config) => {
59-
if (err) {
60-
return reject(err);
61-
}
62-
63-
// Connect to the database
64-
return resolve(Knex({
65-
client: process.env.SQL_CLIENT,
66-
connection: config
67-
}));
68-
});
69-
});
70-
}
71-
// [END getConnection]
72-
73-
exports.main = function () {
74-
// [START main]
75-
getConnection()
76-
.then((knex) => {
77-
return createTable(knex);
78-
})
79-
.then((knex) => {
80-
return knex.destroy();
81-
})
82-
.catch((err, knex) => {
83-
console.error(`Failed to create database connection:`, err);
84-
if (knex) {
85-
knex.destroy();
86-
}
87-
});
88-
// [END main]
89-
};
52+
});
9053
// [END createTables]
91-
92-
// Get type of SQL client to use
93-
const sqlClient = process.env.SQL_CLIENT;
94-
if (sqlClient === 'pg' || sqlClient === 'mysql') {
95-
exports.main();
96-
} else {
97-
throw new Error(`The SQL_CLIENT environment variable must be set to lowercase 'pg' or 'mysql'.`);
98-
}

appengine/cloudsql/package.json

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "appengine-cloudsql",
3-
"description": "Sample for Google Cloud SQL on Google App Engine Flexible Environment.",
2+
"name": "appengine-cloudsql-mysql",
3+
"description": "Node.js MySQL sample for Cloud SQL on App Engine flexible environment.",
44
"version": "0.0.1",
55
"private": true,
66
"license": "Apache-2.0",
@@ -14,7 +14,6 @@
1414
},
1515
"scripts": {
1616
"deploy": "gcloud app deploy",
17-
"start": "node server.js",
1817
"lint": "samples lint",
1918
"pretest": "npm run lint",
2019
"unit-test": "ava --verbose test/*.test.js",
@@ -30,7 +29,6 @@
3029
"express": "4.15.4",
3130
"knex": "0.13.0",
3231
"mysql": "2.14.1",
33-
"pg": "7.2.0",
3432
"prompt": "1.0.0"
3533
},
3634
"devDependencies": {
@@ -43,22 +41,20 @@
4341
"test": {
4442
"app": {
4543
"requiredEnvVars": [
46-
"SQL_CLIENT",
4744
"SQL_USER",
4845
"SQL_PASSWORD",
4946
"SQL_DATABASE",
5047
"SQL_PORT",
5148
"INSTANCE_CONNECTION_NAME"
5249
],
5350
"msg": "Last 10 visits:",
54-
"substitutions": "YOUR_SQL_CLIENT=$SQL_CLIENT,YOUR_USER=$SQL_USER,YOUR_PASSWORD=$SQL_PASSWORD,YOUR_DATABASE=$SQL_DATABASE,YOUR_INSTANCE_CONNECTION_NAME=$INSTANCE_CONNECTION_NAME",
51+
"substitutions": "YOUR_SQL_USER=$SQL_USER,YOUR_SQL_PASSWORD=$SQL_PASSWORD,YOUR_SQL_DATABASE=$SQL_DATABASE,YOUR_INSTANCE_CONNECTION_NAME=$INSTANCE_CONNECTION_NAME",
5552
"args": [
5653
"server.js"
5754
]
5855
},
5956
"build": {
6057
"requiredEnvVars": [
61-
"SQL_CLIENT",
6258
"SQL_USER",
6359
"SQL_PASSWORD",
6460
"SQL_DATABASE",

appengine/cloudsql/server.js

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@
1919
const process = require('process');
2020

2121
// [START app]
22-
// [START setup]
2322
const express = require('express');
2423
const Knex = require('knex');
2524
const crypto = require('crypto');
2625

2726
const app = express();
2827
app.enable('trust proxy');
29-
// [END setup]
30-
let knex;
28+
29+
const knex = connect();
3130

3231
function connect () {
3332
// [START connect]
@@ -38,39 +37,37 @@ function connect () {
3837
};
3938

4039
if (process.env.INSTANCE_CONNECTION_NAME && process.env.NODE_ENV === 'production') {
41-
if (process.env.SQL_CLIENT === 'mysql') {
42-
config.socketPath = `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`;
43-
} else if (process.env.SQL_CLIENT === 'pg') {
44-
config.host = `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`;
45-
}
40+
config.socketPath = `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`;
4641
}
4742

4843
// Connect to the database
4944
const knex = Knex({
50-
client: process.env.SQL_CLIENT,
45+
client: 'mysql',
5146
connection: config
5247
});
5348
// [END connect]
5449

5550
return knex;
5651
}
5752

58-
// [START insertVisit]
5953
/**
6054
* Insert a visit record into the database.
6155
*
56+
* @param {object} knex The Knex connection object.
6257
* @param {object} visit The visit record to insert.
58+
* @returns {Promise}
6359
*/
64-
function insertVisit (visit) {
60+
function insertVisit (knex, visit) {
6561
return knex('visits').insert(visit);
6662
}
67-
// [END insertVisit]
6863

69-
// [START getVisits]
7064
/**
7165
* Retrieve the latest 10 visit records from the database.
66+
*
67+
* @param {object} knex The Knex connection object.
68+
* @returns {Promise}
7269
*/
73-
function getVisits () {
70+
function getVisits (knex) {
7471
return knex.select('timestamp', 'userIp')
7572
.from('visits')
7673
.orderBy('timestamp', 'desc')
@@ -79,7 +76,6 @@ function getVisits () {
7976
return results.map((visit) => `Time: ${visit.timestamp}, AddrHash: ${visit.userIp}`);
8077
});
8178
}
82-
// [END getVisits]
8379

8480
app.get('/', (req, res, next) => {
8581
// Create a visit record to be stored in the database
@@ -89,11 +85,9 @@ app.get('/', (req, res, next) => {
8985
userIp: crypto.createHash('sha256').update(req.ip).digest('hex').substr(0, 7)
9086
};
9187

92-
insertVisit(visit)
93-
.then(() => {
94-
// Query the last 10 visits from the database.
95-
return getVisits();
96-
})
88+
insertVisit(knex, visit)
89+
// Query the last 10 visits from the database.
90+
.then(() => getVisits(knex))
9791
.then((visits) => {
9892
res
9993
.status(200)
@@ -106,21 +100,11 @@ app.get('/', (req, res, next) => {
106100
});
107101
});
108102

109-
// Get type of SQL client to use
110-
const sqlClient = process.env.SQL_CLIENT;
111-
if (sqlClient === 'pg' || sqlClient === 'mysql') {
112-
knex = connect();
113-
} else {
114-
throw new Error(`The SQL_CLIENT environment variable must be set to lowercase 'pg' or 'mysql'.`);
115-
}
116-
117-
// [START listen]
118103
const PORT = process.env.PORT || 8080;
119104
app.listen(PORT, () => {
120105
console.log(`App listening on port ${PORT}`);
121106
console.log('Press Ctrl+C to quit.');
122107
});
123-
// [END listen]
124108
// [END app]
125109

126110
module.exports = app;

0 commit comments

Comments
 (0)