[go: up one dir, main page]

Skip to content

Commit

Permalink
feat(spanner): add emulator support for the admin client autogenerate…
Browse files Browse the repository at this point in the history
…d API samples (#1994)

This PR introduces emulator support for the API samples, which are using admin client autogenerated methods.

**Sample usage**

For Instance samples:

```
const {Spanner} = require('@google-cloud/spanner');
const spanner = new Spanner({
    projectId: projectId,
  });
 const instanceAdminClient = spanner.get_instance_admin_client();
```

For Database samples:

```
const {Spanner} = require('@google-cloud/spanner');
const spanner = new Spanner({
    projectId: projectID,
  });
const databaseAdminClient = spanner.get_database_admin_client();
```
  • Loading branch information
alkatrivedi committed Feb 28, 2024
1 parent 53e529f commit e2fe5b7
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -13,3 +13,4 @@ system-test/*key.json
package-lock.json
__pycache__
.idea
.vscode
58 changes: 57 additions & 1 deletion src/index.ts
Expand Up @@ -46,7 +46,13 @@ import {
CreateInstanceConfigCallback,
CreateInstanceConfigResponse,
} from './instance-config';
import {grpc, GrpcClientOptions, CallOptions, GoogleError} from 'google-gax';
import {
grpc,
GrpcClientOptions,
CallOptions,
GoogleError,
ClientOptions,
} from 'google-gax';
import {google, google as instanceAdmin} from '../protos/protos';
import {
PagedOptions,
Expand Down Expand Up @@ -347,6 +353,54 @@ class Spanner extends GrpcService {
this.directedReadOptions = directedReadOptions;
}

/**
* Gets the InstanceAdminClient object.
* The returned InstanceAdminClient object is a shared, managed instance and should not be manually closed.
* @returns {v1.InstanceAdminClient} The InstanceAdminClient object
* @example
* ```
* const {Spanner} = require('@google-cloud/spanner');
* const spanner = new Spanner({
* projectId: projectId,
* });
* const instanceAdminClient = spanner.getInstanceAdminClient();
* ```
*/
getInstanceAdminClient(): v1.InstanceAdminClient {
const clientName = 'InstanceAdminClient';
if (!this.clients_.has(clientName)) {
this.clients_.set(
clientName,
new v1[clientName](this.options as ClientOptions)
);
}
return this.clients_.get(clientName)! as v1.InstanceAdminClient;
}

/**
* Gets the DatabaseAdminClient object.
* The returned DatabaseAdminClient object is a managed, shared instance and should not be manually closed.
* @returns {v1.DatabaseAdminClient} The DatabaseAdminClient object.
* @example
* ```
* const {Spanner} = require('@google-cloud/spanner');
* const spanner = new Spanner({
* projectId: projectId,
* });
* const databaseAdminClient = spanner.getDatabaseAdminClient();
* ```
*/
getDatabaseAdminClient(): v1.DatabaseAdminClient {
const clientName = 'DatabaseAdminClient';
if (!this.clients_.has(clientName)) {
this.clients_.set(
clientName,
new v1[clientName](this.options as ClientOptions)
);
}
return this.clients_.get(clientName)! as v1.DatabaseAdminClient;
}

/** Closes this Spanner client and cleans up all resources used by it. */
close(): void {
this.clients_.forEach(c => {
Expand Down Expand Up @@ -1741,6 +1795,8 @@ promisifyAll(Spanner, {
'pgJsonb',
'operation',
'timestamp',
'getInstanceAdminClient',
'getDatabaseAdminClient',
],
});

Expand Down
109 changes: 109 additions & 0 deletions system-test/spanner.ts
Expand Up @@ -231,6 +231,115 @@ describe('Spanner', () => {
);
});

describe('Autogenerated Admin Client', async () => {
const projectId = process.env.GCLOUD_PROJECT;
const instanceId = envInstanceName
? envInstanceName
: generateName('instance');
const DATABASE = generateName('database');
const instanceAdminClient = spanner.getInstanceAdminClient();
const databaseAdminClient = spanner.getDatabaseAdminClient();

before(async () => {
assert(projectId);
if (generateInstanceForTest) {
const [operation] = await instanceAdminClient.createInstance({
parent: instanceAdminClient.projectPath(projectId),
instanceId: instanceId,
instance: {
config: instanceAdminClient.instanceConfigPath(
projectId,
'regional-us-central1'
),
nodeCount: 1,
displayName: instanceId,
labels: {
cloud_spanner_samples: 'true',
created: Math.round(Date.now() / 1000).toString(), // current time
},
},
});
const [instance] = await operation.promise();
RESOURCES_TO_CLEAN.push(instance as Instance);
} else {
console.log(
`Not creating temp instance, using + ${instanceAdminClient.instancePath(
projectId,
envInstanceName
)}...`
);
}
const [operation] = await databaseAdminClient.createDatabase({
createStatement: 'CREATE DATABASE `' + DATABASE + '`',
extraStatements: [
`CREATE TABLE ${TABLE_NAME} (
SingerId STRING(1024) NOT NULL,
Name STRING(1024),
) PRIMARY KEY(SingerId)`,
],
parent: databaseAdminClient.instancePath(projectId, instanceId),
});
await operation.promise();
});

describe('Instances', () => {
it('should have created the instance', async () => {
assert(projectId);
try {
const [metadata] = await instanceAdminClient.getInstance({
name: instanceAdminClient.instancePath(projectId, instanceId),
});
assert.strictEqual(
metadata!.name,
instanceAdminClient.instancePath(projectId, instanceId)
);
} catch (err) {
if (!err) {
assert.ifError(err);
}
}
});

it('should list the instances', async () => {
assert(projectId);
const [instances] = await instanceAdminClient.listInstances({
parent: instanceAdminClient.projectPath(projectId),
});
assert(instances!.length > 0);
});
});

describe('Databases', () => {
async function createDatabase(database, dialect) {
assert(projectId);
const [metadata] = await databaseAdminClient.getDatabase({
name: databaseAdminClient.databasePath(
projectId,
instanceId,
database
),
});
assert.strictEqual(
metadata!.name,
databaseAdminClient.databasePath(projectId, instanceId, database)
);
assert.strictEqual(metadata!.state, 'READY');
if (IS_EMULATOR_ENABLED) {
assert.strictEqual(
metadata!.databaseDialect,
'DATABASE_DIALECT_UNSPECIFIED'
);
} else {
assert.strictEqual(metadata!.databaseDialect, dialect);
}
}

it('GOOGLE_STANDARD_SQL should have created the database', async () => {
createDatabase(DATABASE, 'GOOGLE_STANDARD_SQL');
});
});
});

describe('types', () => {
const TABLE_NAME = 'TypeCheck';
const googleSqlTable = DATABASE.table(TABLE_NAME);
Expand Down
2 changes: 2 additions & 0 deletions test/index.ts
Expand Up @@ -91,6 +91,8 @@ const fakePfy = extend({}, pfy, {
'pgJsonb',
'operation',
'timestamp',
'getInstanceAdminClient',
'getDatabaseAdminClient',
]);
},
});
Expand Down

0 comments on commit e2fe5b7

Please sign in to comment.