Skip to content

Commit a279275

Browse files
feat: update CloudSQL samples to reflect updated TCP and Unix Socket connection methods (GoogleCloudPlatform#1130)
1 parent 1328c2f commit a279275

File tree

10 files changed

+449
-141
lines changed

10 files changed

+449
-141
lines changed

cloud_sql/mysql/pdo/README.md

Lines changed: 118 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,91 +2,169 @@
22

33
## Before you begin
44

5-
1. Before you use this code sample, you need to have [Composer](https://getcomposer.org/) installed or downloaded into this folder. Download instructions can be found [here](https://getcomposer.org/download/). Once you've installed composer, use it to install required dependencies by running `composer install`.
6-
2. Create a MySQL Cloud SQL Instance by following these [instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note the connection string, database user, and database password that you create.
7-
3. Create a database for your application by following these [instructions](https://cloud.google.com/sql/docs/mysql/create-manage-databases). Note the database name.
8-
4. Create a service account with the 'Cloud SQL Client' permissions by following these [instructions](https://cloud.google.com/sql/docs/mysql/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). Download a JSON key to use to authenticate your connection.
5+
1. Before you use this code sample, you need to have
6+
[Composer](https://getcomposer.org/) installed or downloaded into this folder.
7+
Download instructions can be found [here](https://getcomposer.org/download/).
8+
Once you've installed composer, use it to install required dependencies by
9+
running `composer install`.
10+
2. Create a MySQL Cloud SQL Instance by following these
11+
[instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note
12+
the connection string, database user, and database password that you create.
13+
3. Create a database for your application by following these
14+
[instructions](https://cloud.google.com/sql/docs/mysql/create-manage-databases).
15+
Note the database name.
16+
4. Create a service account with the 'Cloud SQL Client' permissions by following
17+
these
18+
[instructions](https://cloud.google.com/sql/docs/mysql/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account).
19+
Download a JSON key to use to authenticate your connection.
920

1021
## Running Locally
1122

12-
To run this application locally, download and install the `cloud_sql_proxy` by following the instructions [here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install).
23+
To run this application locally, download and install the `cloud_sql_proxy` by
24+
following the instructions [here](https://cloud.google.com/sql/docs/mysql/sql-proxy#install).
1325

14-
To authenticate with Cloud SQL, set the `$GOOGLE_APPLICATION_CREDENTIALS` environment variable:
26+
Instructions are provided below for using the proxy with a TCP connection or a
27+
Unix domain socket. On Linux or macOS, you can use either option, but the
28+
Windows proxy currently requires a TCP connection.
29+
30+
### Unix Socket mode
31+
NOTE: this option is currently only supported on Linux and macOS. Windows users
32+
should use the TCP option.
33+
34+
To use a Unix socket, you'll need to create a directory and give write access to
35+
the user running the proxy:
1536

1637
```bash
17-
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
38+
sudo mkdir /path/to/the/new/directory
39+
sudo chown -R $USER /path/to/the/new/directory
1840
```
1941

20-
To run the Cloud SQL proxy, you need to set the instance connection name. See the instructions [here](https://cloud.google.com/sql/docs/mysql/quickstart-proxy-test#get_the_instance_connection_name) for finding the instance connection name.
42+
You'll also need to initialize an environment variable pointing to the directory
43+
you just created:
2144

2245
```bash
23-
export CLOUD_SQL_CONNECTION_NAME='::'
46+
export DB_SOCKET_DIR=/path/to/the/new/directory
2447
```
2548

26-
Once the proxy is ready, use one of the following commands to start the proxy in the background.
49+
Use these terminal commands to initialize other environment variables as well:
2750

28-
You may connect to your instance via either unix sockets or TCP. To connect using a socket, you must provide the `-dir` option when starting the proxy. To connect via TCP, you must provide a port as part of the instance name. Both are demonstrated below.
51+
```bash
52+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
53+
export CLOUD_SQL_CONNECTION_NAME='::'
54+
export DB_USER=''
55+
export DB_PASS=''
56+
export DB_NAME=''
57+
```
2958

30-
### Unix Socket mode
59+
Note: Saving credentials in environment variables is convenient, but not
60+
secure - consider a more secure solution such as
61+
[Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets
62+
safe.
63+
64+
Then use the following command to launch the proxy in the background:
3165

3266
```bash
33-
$ ./cloud_sql_proxy -dir=/cloudsql \
34-
--instances=$CLOUD_SQL_CONNECTION_NAME \
35-
--credential_file=$GOOGLE_APPLICATION_CREDENTIALS
67+
./cloud_sql_proxy -dir=$DB_SOCKET_DIR --instances=$CLOUD_SQL_CONNECTION_NAME --credential_file=$GOOGLE_APPLICATION_CREDENTIALS &
3668
```
3769

38-
Note: Make sure to run the command under a user with write access in the `/cloudsql` directory. This proxy will use this folder to create a unix socket the application will use to connect to Cloud SQL.
39-
4070
### TCP mode
71+
To run the sample locally with a TCP connection, set environment variables and
72+
launch the proxy as shown below.
73+
74+
#### Linux / macOS
75+
Use these terminal commands to initialize environment variables:
4176

4277
```bash
43-
$ ./cloud_sql_proxy \
44-
--instances=$CLOUD_SQL_CONNECTION_NAME=tcp:3306 \
45-
--credential_file=$GOOGLE_APPLICATION_CREDENTIALS
78+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
79+
export CLOUD_SQL_CONNECTION_NAME='::'
80+
export DB_HOST='127.0.0.1'
81+
export DB_USER=''
82+
export DB_PASS=''
83+
export DB_NAME=''
4684
```
4785

48-
### Set Configuration Values
49-
Set the required environment variables for your connection to Cloud SQL. If you are using TCP mode as described above, do not set the `CLOUD_SQL_CONNECTION_NAME` variable.
86+
Note: Saving credentials in environment variables is convenient, but not
87+
secure - consider a more secure solution such as
88+
[Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets
89+
safe.
90+
91+
Then use the following command to launch the proxy in the background:
5092

5193
```bash
52-
export DB_USER='my-db-user'
53-
export DB_PASS='my-db-pass'
54-
export DB_NAME='my-db-name'
55-
export DB_HOSTNAME='localhost'
94+
./cloud_sql_proxy -instances=$CLOUD_SQL_CONNECTION_NAME=tcp:3306 -credential_file=$GOOGLE_APPLICAITON_CREDENTIALS &
5695
```
5796

58-
Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets safe.
97+
#### Windows/PowerShell
98+
Use these PowerShell commands to initialize environment variables:
5999

60-
Execute the following:
100+
```powershell
101+
$env:GOOGLE_APPLICATION_CREDENTIALS=""
102+
$env:DB_HOST="127.0.0.1"
103+
$env:DB_USER=""
104+
$env:DB_PASS=""
105+
$env:DB_NAME=""
106+
```
61107

62-
```bash
63-
$ php -S localhost:8080
108+
Note: Saving credentials in environment variables is convenient, but not
109+
secure - consider a more secure solution such as
110+
[Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets
111+
safe.
112+
113+
Then use the following command to launch the proxy in a separate PowerShell
114+
session:
115+
116+
```powershell
117+
Start-Process -filepath "C:\" -ArgumentList "-instances=::=tcp:3306 -credential_file="
118+
```
119+
120+
### Testing the application
121+
Execute the following to start the application server:
122+
``` bash
123+
php -S localhost:8080
64124
```
65125

66-
Navigate towards http://localhost:8080 to verify your application is running correctly.
126+
Navigate towards http://localhost:8080 to verify your application is running
127+
correctly.
67128

68129
## Google App Engine Flex
130+
To run on App Engine Flex, create an App Engine project by following the setup
131+
for these
132+
[instructions](https://cloud.google.com/appengine/docs/standard/php7/quickstart#before-you-begin).
69133

70-
To run on App Engine Flex, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/standard/php7/quickstart#before-you-begin).
134+
First, update `app.flex.yaml` with the correct values to pass the environment
135+
variables into the runtime.
71136

72-
First, update `app.yaml` with the correct values to pass the environment variables into the runtime.
137+
To use a TCP connection instead of a Unix socket to connect your sample to your
138+
Cloud SQL instance on App Engine, make sure to uncomment the `DB_HOST`
139+
field under `env_variables`. Also make sure to remove the uncommented
140+
`beta_settings` and `cloud_sql_instances` fields and replace them with the
141+
commented `beta_settings` and `cloud_sql_instances` fields.
73142

74-
Then, make sure that the service account `service-{PROJECT_NUMBER}>@gae-api-prod.google.com.iam.gserviceaccount.com` has the IAM role `Cloud SQL Client`.
143+
Then, make sure that the service account
144+
`service-{PROJECT_NUMBER}>@gae-api-prod.google.com.iam.gserviceaccount.com` has
145+
the IAM role `Cloud SQL Client`.
75146

76-
Next, the following command will deploy the application to your Google Cloud project:
147+
Next, the following command will deploy the application to your Google Cloud
148+
project:
77149

78150
```bash
79-
$ gcloud beta app deploy
151+
$ gcloud beta app deploy app.flex.yaml
80152
```
81153

82154
## Google App Engine Standard
155+
Note: App Engine Standard does not support TCP connections to Cloud SQL
156+
instances, only Unix socket connections.
83157

84-
To run on GAE-Standard, create an App Engine project by following the setup for these [instructions](https://cloud.google.com/appengine/docs/standard/php7/quickstart#before-you-begin).
158+
To run on GAE-Standard, create an App Engine project by following the setup for
159+
these
160+
[instructions](https://cloud.google.com/appengine/docs/standard/php7/quickstart#before-you-begin).
85161

86-
First, update `app.yaml` with the correct values to pass the environment variables into the runtime.
162+
First, update `app.standard.yaml` with the correct values to pass the
163+
environment variables into the runtime.
87164

88-
Next, the following command will deploy the application to your Google Cloud project:
165+
Next, the following command will deploy the application to your Google Cloud
166+
project:
89167

90168
```bash
91-
$ gcloud app deploy app-standard.yaml
169+
$ gcloud app deploy app.standard.yaml
92170
```

cloud_sql/mysql/pdo/app.yaml renamed to cloud_sql/mysql/pdo/app.flex.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,20 @@ env_variables:
2424
DB_PASS: my-db-pass
2525
DB_NAME: my-db
2626

27+
# TCP domain socket setup; uncomment if using a TCP domain socket
28+
# DB_HOST: 172.17.0.1
29+
30+
31+
# Choose to enable either a TCP or Unix domain socket for your database
32+
# connection:
33+
# Enable a Unix domain socket:
2734
beta_settings:
2835
cloud_sql_instances: "::"
2936

37+
# Enable a TCP domain socket:
38+
# beta_settings:
39+
# cloud_sql_instances: "::=tcp:3306"
40+
3041
runtime_config:
3142
document_root: .
3243

cloud_sql/mysql/pdo/src/app.php

Lines changed: 91 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,47 +35,110 @@
3535

3636
// Setup the database connection in the container.
3737
$container['db'] = function () {
38+
# [START cloud_sql_mysql_pdo_timeout]
39+
// Here we set the connection timeout to five seconds and ask PDO to
40+
// throw an exception if any errors occur.
41+
$conn_config = [
42+
PDO::ATTR_TIMEOUT => 5,
43+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
44+
];
45+
# [END cloud_sql_mysql_pdo_timeout]
46+
47+
if (empty(getenv('DB_HOST'))) {
48+
return init_unix_database_connection($conn_config);
49+
} else {
50+
return init_tcp_database_connection($conn_config);
51+
}
52+
};
53+
54+
/**
55+
* @param $conn_config array driver-specific options for PDO
56+
*/
57+
function init_tcp_database_connection(array $conn_config) : PDO
58+
{
3859
$username = getenv('DB_USER');
3960
$password = getenv('DB_PASS');
40-
$dbName = getenv('DB_NAME');
41-
$hostname = getenv('DB_HOSTNAME');
61+
$db_name = getenv('DB_NAME');
62+
$host = getenv('DB_HOST');
63+
64+
try {
65+
# [START cloud_sql_mysql_pdo_create_tcp]
66+
// // $username = 'your_db_user';
67+
// // $password = 'yoursupersecretpassword';
68+
// // $db_name = 'your_db_name';
69+
// // $host = "127.0.0.1";
70+
71+
// Connect using TCP
72+
$dsn = sprintf('mysql:dbname=%s;host=%s', $db_name, $host);
73+
74+
// Connect to the database.
75+
$conn = new PDO($dsn, $username, $password, $conn_config);
76+
# [END cloud_sql_mysql_pdo_create_tcp]
77+
} catch (TypeError $e) {
78+
throw new RuntimeException(
79+
sprintf(
80+
'Invalid or missing configuration! Make sure you have set ' .
81+
'$username, $password, $db_name, and $host (for TCP mode) ' .
82+
'or $cloud_sql_connection_name (for UNIX socket mode). ' .
83+
'The PHP error was %s',
84+
$e->getMessage()
85+
),
86+
$e->getCode(),
87+
$e
88+
);
89+
} catch (PDOException $e) {
90+
throw new RuntimeException(
91+
sprintf(
92+
'TCP Could not connect to the Cloud SQL Database. Check that ' .
93+
'your username and password are correct, that the Cloud SQL ' .
94+
'proxy is running, and that the database exists and is ready ' .
95+
'for use. For more assistance, refer to %s. The PDO error was %s',
96+
'https://cloud.google.com/sql/docs/mysql/connect-external-app',
97+
$e->getMessage()
98+
),
99+
$e->getCode(),
100+
$e
101+
);
102+
}
103+
104+
return $conn;
105+
}
106+
107+
/**
108+
* @param $conn_config array driver-specific options for PDO
109+
*/
110+
function init_unix_database_connection(array $conn_config) : PDO
111+
{
112+
$username = getenv('DB_USER');
113+
$password = getenv('DB_PASS');
114+
$db_name = getenv('DB_NAME');
42115
$cloud_sql_connection_name = getenv('CLOUD_SQL_CONNECTION_NAME');
116+
$socket_dir = getenv('DB_SOCKET_DIR') ?: '/cloudsql';
43117

44118
try {
45-
// # [START cloud_sql_mysql_pdo_create]
119+
// # [START cloud_sql_mysql_pdo_create_socket]
46120
// // $username = 'your_db_user';
47121
// // $password = 'yoursupersecretpassword';
48-
// // $dbName = 'your_db_name';
122+
// // $db_name = 'your_db_name';
49123
// // $cloud_sql_connection_name = getenv("CLOUD_SQL_CONNECTION_NAME");
50-
// // $hostname = "127.0.0.1"; // Only used in TCP mode.
51-
52-
if ($hostname) {
53-
// Connect using TCP
54-
$dsn = sprintf('mysql:dbname=%s;host=%s', $dbName, $hostname);
55-
} else {
56-
// Connect using UNIX sockets
57-
$dsn = sprintf(
58-
'mysql:dbname=%s;unix_socket=/cloudsql/%s',
59-
$dbName,
60-
$cloud_sql_connection_name
61-
);
62-
}
124+
// // $socket_dir = getenv('DB_SOCKET_DIR') ?: '/cloudsql';
125+
126+
// Connect using UNIX sockets
127+
$dsn = sprintf(
128+
'mysql:dbname=%s;unix_socket=%s/%s',
129+
$db_name,
130+
$socket_dir,
131+
$cloud_sql_connection_name
132+
);
63133

64134
// Connect to the database.
65-
# [START cloud_sql_mysql_pdo_timeout]
66-
// Here we set the connection timeout to five seconds and ask PDO to
67-
// throw an exception if any errors occur.
68-
$conn = new PDO($dsn, $username, $password, [
69-
PDO::ATTR_TIMEOUT => 5,
70-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
71-
]);
72-
# [END cloud_sql_mysql_pdo_timeout]
73-
# [END cloud_sql_mysql_pdo_create]
135+
$conn = new PDO($dsn, $username, $password, $conn_config);
136+
# [END cloud_sql_mysql_pdo_create_socket]
74137
} catch (TypeError $e) {
75138
throw new RuntimeException(
76139
sprintf(
77140
'Invalid or missing configuration! Make sure you have set ' .
78-
'$username, $password, $dbName, and $hostname (for TCP mode) ' .
141+
'$username, $password, $db_name, and $host (for TCP mode) ' .
79142
'or $cloud_sql_connection_name (for UNIX socket mode). ' .
80143
'The PHP error was %s',
81144
$e->getMessage()
@@ -99,7 +162,7 @@
99162
}
100163

101164
return $conn;
102-
};
165+
}
103166

104167
// Configure the templating engine.
105168
$container['view'] = function () {

0 commit comments

Comments
 (0)