@google-cloud/bigtable
Version:
Cloud Bigtable Client Library for Node.js
483 lines • 18.4 kB
JavaScript
;
// Copyright 2016 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
//
// https://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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cluster = void 0;
const promisify_1 = require("@google-cloud/promisify");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pumpify = require('pumpify');
const cluster_1 = require("./utils/cluster");
const backup_1 = require("./backup");
const stream_1 = require("stream");
const extend = require("extend");
/**
* Create a cluster object to interact with your cluster.
*
* @class
* @param {Instance} instance The parent instance of this cluster.
* @param {string} id Id of the cluster.
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
* const cluster = instance.cluster('my-cluster');
* ```
*/
class Cluster {
bigtable;
instance;
id;
name;
metadata;
constructor(instance, id) {
this.bigtable = instance.bigtable;
this.instance = instance;
let name;
if (id.includes('/')) {
if (id.startsWith(`${instance.name}/clusters/`)) {
name = id;
}
else {
throw new Error(`Cluster id '${id}' is not formatted correctly.
Please use the format 'my-cluster' or '${instance.name}/clusters/my-cluster'.`);
}
}
else {
name = `${instance.name}/clusters/${id}`;
}
this.id = name.split('/').pop();
this.name = name;
}
/**
* Formats zone location.
*
* @private
*
* @param {string} project The project ID.
* @param {string} location The zone location.
* @returns {string}
*
* @example
* ```
* Cluster.getLocation_('my-project', 'us-central1-b');
* // 'projects/my-project/locations/us-central1-b'
* ```
*/
static getLocation_(project, location) {
if (location.includes('/')) {
return location;
}
// in-case project has '/', split and pick last component
if (project.includes('/')) {
project = project.split('/').pop();
}
return `projects/${project}/locations/${location}`;
}
/**
* Maps the storage type to the proper integer.
*
* @private
*
* @param {string} type The storage type (hdd, ssd).
* @returns {number}
*
* @example
* ```
* Cluster.getStorageType_('ssd');
* // 1
* ```
*/
static getStorageType_(type) {
const storageTypes = {
unspecified: 0,
ssd: 1,
hdd: 2,
};
if (typeof type === 'string') {
type = type.toLowerCase();
}
return storageTypes[type] || storageTypes.unspecified;
}
/**
* Get a reference to a Bigtable Cluster.
*
* @param {string} id The backup name or id.
* @returns {Backup}
*/
backup(id) {
return new backup_1.Backup(this, id);
}
/**
* Create a cluster.
*
* @param {object} [options] See {@link Instance#createCluster}.
* @param {function} [callback] The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_create_cluster
*/
create(optionsOrCallback, cb) {
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const options = typeof optionsOrCallback === 'object' && optionsOrCallback
? optionsOrCallback
: {};
this.instance.createCluster(this.id, options, callback);
}
/**
* Backup a table from this cluster.
*
* @param {string} id A unique ID for the backup.
* @param {object} config Configuration object.
* @param {BackupTimestamp} config.expireTime When the backup will be
* automatically deleted.
* @param {string|Table} config.table Table to create the backup from.
* @param {CallOptions} [config.gaxOptions] Request configuration options,
* outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {CreateBackupCallback} [callback] The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Backup} callback.backup The newly created Backup.
* @param {Operation} callback.operation An operation object that can be used
* to check the status of the request.
* @param {object} callback.apiResponse The full API response.
* @return {void | Promise<CreateBackupResponse>}
*
* @example <caption>include:samples/api-reference-doc-snippets/backups.create.js</caption>
* region_tag:bigtable_api_create_backup
*/
createBackup(id, config, callback) {
if (!id) {
throw new TypeError('An id is required to create a backup.');
}
if (typeof config !== 'object') {
throw new Error('A configuration object is required.');
}
const table = config.table;
if (!table) {
throw new Error('A source table is required to backup.');
}
const reqOpts = {
parent: this.name,
backupId: id,
backup: {
sourceTable: typeof table === 'string' ? table : table.name,
...config,
},
};
cluster_1.ClusterUtils.formatBackupExpiryTime(reqOpts.backup);
delete reqOpts.backup.table;
delete reqOpts.backup.gaxOptions;
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'createBackup',
reqOpts,
gaxOpts: config.gaxOptions,
}, (err, ...args) => {
if (err) {
callback(err, undefined, ...args);
return;
}
callback(null, this.backup(id), ...args);
});
}
/**
* Delete the cluster.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_delete_cluster
*/
delete(gaxOptionsOrCallback, cb) {
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
const gaxOptions = typeof gaxOptionsOrCallback === 'object' && gaxOptionsOrCallback
? gaxOptionsOrCallback
: {};
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'deleteCluster',
reqOpts: {
name: this.name,
},
gaxOpts: gaxOptions,
}, callback);
}
/**
* Check if a cluster exists.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {boolean} callback.exists Whether the cluster exists or not.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_exists_cluster
*/
exists(gaxOptionsOrCallback, cb) {
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
const gaxOptions = typeof gaxOptionsOrCallback === 'object' && gaxOptionsOrCallback
? gaxOptionsOrCallback
: {};
this.getMetadata(gaxOptions, (err) => {
if (err) {
if (err.code === 5) {
callback(null, false);
return;
}
callback(err);
return;
}
callback(null, true);
});
}
/**
* Get a cluster if it exists.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_get_cluster
*/
get(gaxOptionsOrCallback, cb) {
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
const gaxOptions = typeof gaxOptionsOrCallback === 'object' && gaxOptionsOrCallback
? gaxOptionsOrCallback
: {};
this.getMetadata(gaxOptions, (err, metadata) => {
callback(err, err ? null : this, metadata);
});
}
/**
* Get Cloud Bigtable Backup instances within this cluster. This returns both
* completed and pending backups.
*
* @param {GetBackupsOptions | GetBackupsCallback} [optionsOrCallback]
* @param {GetBackupsResponse} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Backup[]} callback.backups All matching Backup instances.
* @param {object} callback.apiResponse The full API response.
* @return {void | Promise<ListBackupsResponse>}
*
* @example <caption>include:samples/api-reference-doc-snippets/backups.list.js</caption>
* region_tag:bigtable_api_list_backups
*/
getBackups(optionsOrCallback, cb) {
let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
options = extend(true, {}, options);
const gaxOpts = options.gaxOptions || {};
const reqOpts = {
parent: this.name,
pageSize: gaxOpts.pageSize,
pageToken: gaxOpts.pageToken,
...options,
};
delete gaxOpts.pageSize;
delete gaxOpts.pageToken;
delete reqOpts.autoPaginate;
delete reqOpts.gaxOptions;
if (typeof options.autoPaginate === 'boolean' &&
typeof gaxOpts.autoPaginate === 'undefined') {
gaxOpts.autoPaginate = options.autoPaginate;
}
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'listBackups',
reqOpts,
gaxOpts,
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(err, ...resp) => {
let backups = [];
if (resp[0]) {
backups = resp[0].map((backup) => {
// Instance#getBackups() uses `-` as a cluster id, which tells the
// API to return backups from any cluster.
const backupInstance = this.id === '-'
? this.instance
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
.cluster(backup.name?.match(/clusters\/([^/]+)/)[1])
.backup(backup.name.split('/').pop())
: this.backup(backup.name.split('/').pop());
backupInstance.metadata = backup;
return backupInstance;
});
}
const nextQuery = resp[1] ? Object.assign(options, resp[1]) : null;
const apiResp = resp[2];
callback(err, backups, nextQuery, apiResp);
});
}
/**
* Lists Cloud Bigtable backups within this cluster. Provides both
* completed and pending backups as a readable object stream.
*
* @param {GetBackupsOptions} [options] Configuration object. See
* {@link Cluster#getBackups} for a complete list of options.
* @returns {ReadableStream<Backup>}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
* const cluster = instance.cluster('my-cluster');
*
* cluster.getBackupsStream()
* .on('error', console.error)
* .on('data', function(backup) {
* // backup is a Backup object.
* })
* .on('end', () => {
* // All backups retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* cluster.getBackupsStream()
* .on('data', function(backup) {
* this.end();
* });
* ```
*/
getBackupsStream(options) {
const { gaxOptions, ...restOptions } = options || {};
const reqOpts = {
...restOptions,
parent: this.name,
};
return pumpify.obj([
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'listBackupsStream',
reqOpts,
gaxOpts: gaxOptions,
}),
new stream_1.Transform({
objectMode: true,
transform: (backup, enc, cb) => {
// Instance#getBackupsStream() uses `-` as a cluster id, which tells
// the API to return backups from any cluster.
const backupInstance = this.id === '-'
? this.instance
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
.cluster(backup.name?.match(/clusters\/([^/]+)/)[1])
.backup(backup.name.split('/').pop())
: this.backup(backup.name.split('/').pop());
backupInstance.metadata = backup;
cb(null, backupInstance);
},
}),
]);
}
/**
* Get the cluster metadata.
*
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.metadata The metadata.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_cluster_get_meta
*/
getMetadata(gaxOptionsOrCallback, cb) {
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
const gaxOptions = typeof gaxOptionsOrCallback === 'object' && gaxOptionsOrCallback
? gaxOptionsOrCallback
: {};
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'getCluster',
reqOpts: {
name: this.name,
},
gaxOpts: gaxOptions,
}, (err, resp) => {
if (resp) {
this.metadata = resp;
}
callback(err, resp);
});
}
/**
* Set the cluster metadata.
*
* @param {object} metadata See {@link Instance#createCluster} for the
* available metadata options.
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Operation} callback.operation An operation object that can be used
* to check the status of the request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/cluster.js</caption>
* region_tag:bigtable_api_cluster_set_meta
*/
setMetadata(metadata, gaxOptionsOrCallback, cb) {
cluster_1.ClusterUtils.validateClusterMetadata(metadata);
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
const gaxOptions = typeof gaxOptionsOrCallback === 'object'
? gaxOptionsOrCallback
: {};
const reqOpts = cluster_1.ClusterUtils.getRequestFromMetadata(metadata, this.name);
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'partialUpdateCluster',
reqOpts: reqOpts,
gaxOpts: gaxOptions,
}, (err, resp) => {
callback(err, resp);
});
}
}
exports.Cluster = Cluster;
/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
(0, promisify_1.promisifyAll)(Cluster, {
exclude: ['backup'],
});
/**
* Reference to the {@link Cluster} class.
* @name module:@google-cloud/bigtable.Cluster
* @see Cluster
*/
//# sourceMappingURL=cluster.js.map