diff --git a/cloud_sql/sqlserver/pdo/README.md b/cloud_sql/sqlserver/pdo/README.md index 888a372ce0..55e9488dd4 100644 --- a/cloud_sql/sqlserver/pdo/README.md +++ b/cloud_sql/sqlserver/pdo/README.md @@ -18,10 +18,10 @@ To authenticate with Cloud SQL, set the `$GOOGLE_APPLICATION_CREDENTIALS` enviro export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json ``` -To run the Cloud SQL proxy, you need to set the instance connection name. See the instructions [here](https://cloud.google.com/sql/docs/sqlserver/quickstart-proxy-test#get_the_instance_connection_name) for finding the instance connection name. +To run the Cloud SQL proxy, you need to set the instance connection name. See the instructions [here](https://cloud.google.com/sql/docs/sqlserver/connect-instance-auth-proxy#get-connection-name) for finding the instance connection name. ```bash -export INSTANCE_CONNECTION_NAME='::' +export INSTANCE_CONNECTION_NAME='::' ``` Once the proxy is ready, use one of the following commands to start the proxy in the background. @@ -39,9 +39,9 @@ $ ./cloud_sql_proxy \ Set the required environment variables for your connection to Cloud SQL. ```bash -export DB_USER='my-db-user' -export DB_PASS='my-db-pass' -export DB_NAME='my-db-name' +export DB_USER='' +export DB_PASS='' +export DB_NAME='' export DB_HOST='127.0.0.1' ``` @@ -59,11 +59,17 @@ Navigate towards http://localhost:8080 to verify your application is running cor 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). -First, update `app.yaml` with the correct values to pass the environment variables into the runtime. +First, update [app.yaml](app.yaml) with the correct values to pass the environment variables into the runtime. In order to use the `sqlsrv` extension, you will need to build a [custom runtime](https://cloud.google.com/appengine/docs/flexible/custom-runtimes/quickstart). The `Dockerfile` in this sample contains a simple example of a custom PHP 7.2 runtime based off of the default App Engine Flex image with the `pdo_sqlsrv` extension installed. -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`. +Then, make sure that the App Engine default service account +`@appspot.gserviceaccount.com` has +the IAM role `Cloud SQL Client`. + +Also, make sure that the Cloud Build service account +`cloudbuild@.iam.gserviceaccount.com` has +the IAM role `Cloud SQL Client`. Next, the following command will deploy the application to your Google Cloud project: diff --git a/cloud_sql/sqlserver/pdo/app.yaml b/cloud_sql/sqlserver/pdo/app.yaml index 4eac7f3053..a3bf47174a 100644 --- a/cloud_sql/sqlserver/pdo/app.yaml +++ b/cloud_sql/sqlserver/pdo/app.yaml @@ -19,16 +19,16 @@ env: flex # something like https://cloud.google.com/secret-manager/ to help keep secrets # secret. env_variables: - DB_USER: my-db-user - DB_PASS: my-db-pass - DB_NAME: my-db - DB_HOST: 172.17.0.1 + DB_USER: + DB_PASS: + DB_NAME: + INSTANCE_HOST: 172.17.0.1 beta_settings: # The connection name of your instance, available by using # 'gcloud beta sql instances describe [INSTANCE_NAME]' or from # the Instance details page in the Google Cloud Platform Console. - cloud_sql_instances: ::=tcp:1433 + cloud_sql_instances: ::=tcp:1433 # Defaults to "serve index.php" and "serve public/index.php". Can be used to # serve a custom PHP front controller (e.g. "serve backend/index.php") or to diff --git a/cloud_sql/sqlserver/pdo/composer.json b/cloud_sql/sqlserver/pdo/composer.json index fe18780438..0888a42ecd 100644 --- a/cloud_sql/sqlserver/pdo/composer.json +++ b/cloud_sql/sqlserver/pdo/composer.json @@ -10,8 +10,8 @@ "ext-pdo_sqlsrv": "*", "slim/slim": "^4.5", "slim/twig-view": "^3.1", - "pimple/pimple": "^3.3", - "guzzlehttp/psr7": "^2.0", - "http-interop/http-factory-guzzle": "^1.0" + "slim/http": "^1.0", + "slim/psr7": "^1.0", + "pimple/pimple": "^3.3" } } diff --git a/cloud_sql/sqlserver/pdo/index.php b/cloud_sql/sqlserver/pdo/index.php index b8b8d688f3..c51b728ffd 100644 --- a/cloud_sql/sqlserver/pdo/index.php +++ b/cloud_sql/sqlserver/pdo/index.php @@ -17,7 +17,7 @@ declare(strict_types=1); -use GuzzleHttp\Psr7; +use Slim\Psr7\Factory\StreamFactory; include __DIR__ . '/vendor/autoload.php'; @@ -48,7 +48,8 @@ : 'An error occurred'; } - return $response->withBody(Psr7\stream_for($message)); + $streamFactory = new StreamFactory; + return $response->withBody($streamFactory->createStream($message)); }); $app->run(); diff --git a/cloud_sql/sqlserver/pdo/src/DBInitializer.php b/cloud_sql/sqlserver/pdo/src/DBInitializer.php deleted file mode 100644 index 668db496aa..0000000000 --- a/cloud_sql/sqlserver/pdo/src/DBInitializer.php +++ /dev/null @@ -1,84 +0,0 @@ -getMessage() - ), - $e->getCode(), - $e - ); - } catch (PDOException $e) { - throw new RuntimeException( - sprintf( - 'Could not connect to the Cloud SQL Database. Check that ' . - 'your username and password are correct, that the Cloud SQL ' . - 'proxy is running, and that the database exists and is ready ' . - 'for use. For more assistance, refer to %s. The PDO error was %s', - 'https://cloud.google.com/sql/docs/sqlserver/connect-external-app', - $e->getMessage() - ), - (int) $e->getCode(), - $e - ); - } - - return $conn; - } -} diff --git a/cloud_sql/sqlserver/pdo/src/DatabaseTcp.php b/cloud_sql/sqlserver/pdo/src/DatabaseTcp.php new file mode 100644 index 0000000000..ab73402b20 --- /dev/null +++ b/cloud_sql/sqlserver/pdo/src/DatabaseTcp.php @@ -0,0 +1,94 @@ + 5, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + ] + # [END cloud_sql_sqlserver_pdo_timeout] + # [END_EXCLUDE] + ); + } catch (TypeError $e) { + throw new RuntimeException( + sprintf( + 'Invalid or missing configuration! Make sure you have set ' . + '$username, $password, $dbName, and $instanceHost (for TCP mode). ' . + 'The PHP error was %s', + $e->getMessage() + ), + $e->getCode(), + $e + ); + } catch (PDOException $e) { + throw new RuntimeException( + sprintf( + 'Could not connect to the Cloud SQL Database. Check that ' . + 'your username and password are correct, that the Cloud SQL ' . + 'proxy is running, and that the database exists and is ready ' . + 'for use. For more assistance, refer to %s. The PDO error was %s', + 'https://cloud.google.com/sql/docs/sqlserver/connect-external-app', + $e->getMessage() + ), + (int) $e->getCode(), + $e + ); + } + + return $conn; + } +} +# [END cloud_sql_sqlserver_pdo_connect_tcp] diff --git a/cloud_sql/sqlserver/pdo/src/app.php b/cloud_sql/sqlserver/pdo/src/app.php index cd6e5ed78a..6d18f1c07d 100644 --- a/cloud_sql/sqlserver/pdo/src/app.php +++ b/cloud_sql/sqlserver/pdo/src/app.php @@ -17,7 +17,7 @@ declare(strict_types=1); -use Google\Cloud\Samples\CloudSQL\SQLServer\DBInitializer; +use Google\Cloud\Samples\CloudSQL\SQLServer\DatabaseTcp; use Google\Cloud\Samples\CloudSQL\SQLServer\Votes; use Pimple\Container; use Pimple\Psr11\Container as Psr11Container; @@ -26,7 +26,7 @@ use Slim\Views\TwigMiddleware; // Create and set the dependency injection container. -$container = new Container; +$container = new Container(); AppFactory::setContainer(new Psr11Container($container)); // add the votes manager to the container. @@ -36,40 +36,22 @@ // Setup the database connection in the container. $container['db'] = function () { - # [START cloud_sql_sqlserver_pdo_timeout] - // Here we set the connection timeout to five seconds and ask PDO to - // throw an exception if any errors occur. - $connConfig = [ - PDO::ATTR_TIMEOUT => 5, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION - ]; - # [END cloud_sql_sqlserver_pdo_timeout] - - $username = getenv('DB_USER'); - $password = getenv('DB_PASS'); - $dbName = getenv('DB_NAME'); - $dbHost = getenv('DB_HOST'); - - if (empty($username = getenv('DB_USER'))) { - throw new RuntimeException('Must supply $DB_USER environment variables'); + if (getenv('DB_USER') === false) { + throw new RuntimeException('Must supply $DB_USER environment variable'); } - if (empty($password = getenv('DB_PASS'))) { - throw new RuntimeException('Must supply $DB_PASS environment variables'); + if (getenv('DB_PASS') === false) { + throw new RuntimeException('Must supply $DB_PASS environment variable'); } - if (empty($dbName = getenv('DB_NAME'))) { - throw new RuntimeException('Must supply $DB_NAME environment variables'); + if (getenv('DB_NAME') === false) { + throw new RuntimeException('Must supply $DB_NAME environment variable'); } - if (empty($dbHost = getenv('DB_HOST'))) { - throw new RuntimeException('Must supply $DB_HOST environment variables'); + if (getenv('INSTANCE_HOST') === false) { + throw new RuntimeException( + 'Must supply $INSTANCE_HOST environment variable' + ); } - return DBInitializer::initTcpDatabaseConnection( - $username, - $password, - $dbName, - $dbHost, - $connConfig - ); + return DatabaseTcp::initTcpDatabaseConnection(); }; // Configure the templating engine. diff --git a/cloud_sql/sqlserver/pdo/test/IntegrationTest.php b/cloud_sql/sqlserver/pdo/test/IntegrationTest.php index 0361e7a5dd..217f2ba782 100644 --- a/cloud_sql/sqlserver/pdo/test/IntegrationTest.php +++ b/cloud_sql/sqlserver/pdo/test/IntegrationTest.php @@ -18,13 +18,15 @@ namespace Google\Cloud\Samples\CloudSQL\SQLServer\Tests; -use Google\Cloud\Samples\CloudSQL\SQLServer\DBInitializer; +use Google\Cloud\Samples\CloudSQL\SQLServer\DatabaseTcp; use Google\Cloud\Samples\CloudSQL\SQLServer\Votes; use Google\Cloud\TestUtils\TestTrait; use Google\Cloud\TestUtils\CloudSqlProxyTrait; -use PDO; use PHPUnit\Framework\TestCase; +/** + * @runTestsInSeparateProcesses + */ class IntegrationTest extends TestCase { use TestTrait; @@ -32,7 +34,9 @@ class IntegrationTest extends TestCase public static function setUpBeforeClass(): void { - $connectionName = self::requireEnv('CLOUDSQL_CONNECTION_NAME_SQLSERVER'); + $connectionName = self::requireEnv( + 'CLOUDSQL_CONNECTION_NAME_SQLSERVER' + ); $socketDir = self::requireEnv('DB_SOCKET_DIR'); $port = '1433'; @@ -41,23 +45,17 @@ public static function setUpBeforeClass(): void public function testTcpConnection() { - $conn_config = [ - PDO::ATTR_TIMEOUT => 5, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION - ]; - - $dbHost = $this->requireEnv('SQLSERVER_HOST'); + $instanceHost = $this->requireEnv('SQLSERVER_HOST'); $dbPass = $this->requireEnv('SQLSERVER_PASSWORD'); $dbName = $this->requireEnv('SQLSERVER_DATABASE'); $dbUser = $this->requireEnv('SQLSERVER_USER'); - $votes = new Votes(DBInitializer::initTcpDatabaseConnection( - $dbUser, - $dbPass, - $dbName, - $dbHost, - $conn_config - )); + putenv("INSTANCE_HOST=$instanceHost"); + putenv("DB_PASS=$dbPass"); + putenv("DB_NAME=$dbName"); + putenv("DB_USER=$dbUser"); + + $votes = new Votes(DatabaseTcp::initTcpDatabaseConnection()); $this->assertIsArray($votes->listVotes()); } }