Skip to content

Commit

Permalink
docs: Samples and tests for Database Admin Client APIs (#1986)
Browse files Browse the repository at this point in the history
This PR contains sample files and their integration tests for the database admin client APIs.
  • Loading branch information
alkatrivedi committed Feb 29, 2024
1 parent 494a996 commit f34a33a
Show file tree
Hide file tree
Showing 24 changed files with 2,364 additions and 4 deletions.
482 changes: 478 additions & 4 deletions samples/system-test/v2/spanner.test.js

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions samples/v2/add-and-drop-new-database-role.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2024 Google LLC
//
// 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.

// sample-metadata:
// title: Add and drop new database role
// usage: node add-and-drop-new-database-role.js <INSTANCE_ID> <DATABASE_ID> <PROJECT_ID>

'use strict';

function main(
instanceId = 'my-instance',
databaseId = 'my-database',
projectId = 'my-project-id'
) {
// [START spanner_add_and_drop_database_role]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const projectId = 'my-project-id';

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

// creates a client
const spanner = new Spanner({
projectId: projectId,
});

const databaseAdminClient = spanner.getDatabaseAdminClient();

async function addAndDropNewDatabaseRole() {
// Creates a new user defined role and grant permissions
try {
const request = [
'CREATE ROLE parent',
'GRANT SELECT ON TABLE Singers TO ROLE parent',
'CREATE ROLE child',
'GRANT ROLE parent TO ROLE child',
];
const [operation] = await databaseAdminClient.updateDatabaseDdl({
database: databaseAdminClient.databasePath(
projectId,
instanceId,
databaseId
),
statements: request,
});

console.log('Waiting for operation to complete...');
await operation.promise();

console.log('Created roles child and parent and granted privileges');
} catch (err) {
console.error('ERROR:', err);
}

// Revoke permissions and drop child role.
// A role can't be dropped until all its permissions are revoked.
try {
const request = ['REVOKE ROLE parent FROM ROLE child', 'DROP ROLE child'];
const [operation] = await databaseAdminClient.updateDatabaseDdl({
database: databaseAdminClient.databasePath(
projectId,
instanceId,
databaseId
),
statements: request,
});

console.log('Waiting for operation to complete...');
await operation.promise();

console.log('Revoked privileges and dropped role child');
} catch (err) {
console.error('ERROR:', err);
} finally {
// Close the spanner client when finished.
// The databaseAdminClient does not require explicit closure. The closure of the Spanner client will automatically close the databaseAdminClient.
spanner.close();
}
}
addAndDropNewDatabaseRole();
// [END spanner_add_and_drop_database_role]
}

process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
94 changes: 94 additions & 0 deletions samples/v2/database-create-with-default-leader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Copyright 2024 Google LLC
* 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.
*/

// sample-metadata:
// title: Creates a new database with a specific default leader
// usage: node database-create-with-default-leader.js <INSTANCE_ID> <DATABASE_ID> <DEFAULT_LEADER> <PROJECT_ID>

'use strict';

function main(instanceId, databaseId, defaultLeader, projectId) {
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance-id';
// const databaseId = 'my-database-id';
// const defaultLeader = 'my-default-leader'; example: 'asia-northeast1'

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

// creates a client
const spanner = new Spanner({
projectId: projectId,
});

const databaseAdminClient = spanner.getDatabaseAdminClient();

async function createDatabaseWithDefaultLeader() {
// Create a new database with an extra statement which will alter the
// database after creation to set the default leader.
console.log(
`Creating database ${databaseAdminClient.databasePath(
projectId,
instanceId,
databaseId
)}.`
);
const createSingersTableStatement = `
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX)
) PRIMARY KEY (SingerId)`;
const createAlbumsStatement = `
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX)
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE`;

// Default leader is one of the possible values in the leaderOptions field of the
// instance config of the instance where the database is created.
const setDefaultLeaderStatement = `
ALTER DATABASE \`${databaseId}\`
SET OPTIONS (default_leader = '${defaultLeader}')`;

const [operation] = await databaseAdminClient.createDatabase({
createStatement: 'CREATE DATABASE `' + databaseId + '`',
extraStatements: [
createSingersTableStatement,
createAlbumsStatement,
setDefaultLeaderStatement,
],
parent: databaseAdminClient.instancePath(projectId, instanceId),
});

console.log(`Waiting for creation of ${databaseId} to complete...`);
await operation.promise();
console.log(
`Created database ${databaseId} with default leader ${defaultLeader}.`
);
}
createDatabaseWithDefaultLeader();
}
process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
68 changes: 68 additions & 0 deletions samples/v2/database-create-with-encryption-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

async function createDatabaseWithEncryptionKey(
instanceId,
databaseId,
projectId,
keyName
) {
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const keyName =
// 'projects/my-project-id/my-region/keyRings/my-key-ring/cryptoKeys/my-key';

// Imports the Google Cloud client library
const {Spanner, protos} = require('@google-cloud/spanner');

// creates a client
const spanner = new Spanner({
projectId: projectId,
});

const databaseAdminClient = spanner.getDatabaseAdminClient();

// Creates a database
const [operation] = await databaseAdminClient.createDatabase({
createStatement: 'CREATE DATABASE `' + databaseId + '`',
parent: databaseAdminClient.instancePath(projectId, instanceId),
encryptionConfig:
(protos.google.spanner.admin.database.v1.EncryptionConfig = {
kmsKeyName: keyName,
}),
});

console.log(`Waiting for operation on ${databaseId} to complete...`);
await operation.promise();

console.log(`Created database ${databaseId} on instance ${instanceId}.`);

// Get encryption key
const [metadata] = await databaseAdminClient.getDatabase({
name: databaseAdminClient.databasePath(projectId, instanceId, databaseId),
});

console.log(
`Database encrypted with key ${metadata.encryptionConfig.kmsKeyName}.`
);
}

module.exports.createDatabaseWithEncryptionKey =
createDatabaseWithEncryptionKey;
82 changes: 82 additions & 0 deletions samples/v2/database-create-with-version-retention-period.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Copyright 2024 Google LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

async function createDatabaseWithVersionRetentionPeriod(
instanceId,
databaseId,
projectId
) {
// [START spanner_create_database_with_version_retention_period]

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';

// creates a client
const spanner = new Spanner({
projectId: projectId,
});

const databaseAdminClient = spanner.getDatabaseAdminClient();

try {
// Create a new database with an extra statement which will alter the
// database after creation to set the version retention period.
console.log(
`Creating database ${databaseAdminClient.instancePath(
projectId,
instanceId
)}.`
);
const versionRetentionStatement = `
ALTER DATABASE \`${databaseId}\`
SET OPTIONS (version_retention_period = '1d')`;

const [operation] = await databaseAdminClient.createDatabase({
createStatement: 'CREATE DATABASE `' + databaseId + '`',
extraStatements: [versionRetentionStatement],
parent: databaseAdminClient.instancePath(projectId, instanceId),
});

console.log(`Waiting for operation on ${databaseId} to complete...`);
await operation.promise();
console.log(`
Created database ${databaseId} with version retention period.`);

const [metadata] = await databaseAdminClient.getDatabase({
name: databaseAdminClient.databasePath(projectId, instanceId, databaseId),
});

console.log(`Version retention period: ${metadata.versionRetentionPeriod}`);
const milliseconds =
parseInt(metadata.earliestVersionTime.seconds, 10) * 1000 +
parseInt(metadata.earliestVersionTime.nanos, 10) / 1e6;
const date = new Date(milliseconds);
console.log(`Earliest version time: ${date.toString()}`);
} catch (err) {
console.error('ERROR:', err);
}
// [END spanner_create_database_with_version_retention_period]
}

module.exports.createDatabaseWithVersionRetentionPeriod =
createDatabaseWithVersionRetentionPeriod;

0 comments on commit f34a33a

Please sign in to comment.