API Actions: Lambda
The following is a sample Node.js implementation of an AWS Lambda function that calls the CloudBasic API to execute the following actions:
- Activate an Instance
- Create a User
- Create a new Replication
- Delete a Replication
- Retrieve the Status of a Replication
- Analyze a Replication
- Create a new Cluster
- Delete a Cluster
For the latest version of all CLOUDBASIC examples please refer to our GitHub repositories here
app.js
/* Sample AWS Lambda function to call CBR API Uses the aws4 node.js library (https://github.com/mhart/aws4) to simplify call signing For more information on packaging your custom Lambda function see the AWS documentation (http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html) */ 'use strict'; var httpClient = require('./http-client.js'), deepcopy = require("deepcopy"), CONFIG = require('./config.json'); exports.handler = (event, context, callback) => { scenario(); function scenario() { CONFIG.xml = event.xml; CONFIG.https = event.https; var testCase = "Test case: " + (CONFIG.xml ? " XML " : " JSON ") + '/' + (CONFIG.https ? " HTTPS " : " HTTP ") + "version"; console.log(testCase); var credentials = { accessKeyId: 'ACCESSKEYIDONE', secretAccessKey: 'SECRETACCESSKEYONE' }; var secondCreds = { accessKeyId: 'ACCESSKEYIDTWO', secretAccessKey: 'SECRETACCESSKEYTWO' }; activateInstance('i-011c1c1edd1111dc1', function (credentials) { console.log(`Create Instance ended!`); console.log(credentials); createUser(credentials, function (user) { console.log(` `); console.log(`create user ended!`); console.log(user); createReplication(credentials, function (replication) { console.log(` `); console.log(`create replication ended!`); console.log(replication); replicationStatus(credentials, replication.replicationId, function (replicationStatus) { console.log(` `); console.log(`Replication Status ended!`); console.log(replicationStatus); analyzeReplication(credentials, replication.replicationId, function (data) { console.log(` `); console.log(`Analyze Replication ended!`); console.log(data); deleteReplication(credentials, replication.replicationId, function (data) { console.log(` `); console.log(`Delete Replication ended!`); }); }); }); httpClient.changeHost('your.server2.IP.address'); activateInstance('i-022c2c2edd2222dc2', function (seconCreds) { console.log(` `); console.log(`Create Second Instance ended!`); console.log(seconCreds); }); httpClient.changeHost('your.server1.IP.address'); createCluster(credentials, 'your.server2.IP.address', secondCreds, function (data) { console.log(` `); console.log(`Create Cluster ended!`); deleteCluster(credentials, 'your.server1.IP.address', function (data) { console.log(` `); console.log(`Delete Cluster ended!`); }); }); }); }); //}); } //Activate the insance function activateInstance(instanceId, callback) { var credentials = { accessKeyId: '', secretAccessKey: '' }; var model = deepcopy(CONFIG.activateInstance); model.ActivateInstanceRequest.InstanceId = instanceId; // we can now query the CBR API httpClient.post('ActivateInstance', model, function (res) { //set instance credentials credentials.accessKeyId = res.publicKey; credentials.secretAccessKey = res.privateKey; callback(credentials); }); } //Create User function createUser(creds, callback) { var model = deepcopy(CONFIG.createUser); httpClient.post('CreateUser', model, function (res) { callback(res); }, creds); } //Create Replication function createReplication(creds, callback) { var model = deepcopy(CONFIG.createReplication); httpClient.post('CreateReplication', model, function (res) { callback(res); }, creds); } //Delete Replication function deleteReplication(creds, replicationId, callback) { var model = deepcopy(CONFIG.deleteReplication); model.DeleteReplicationRequest.ReplicationId = replicationId; httpClient.post('DeleteReplication', model, function (res) { callback("Ok"); }, creds); } //Replication Status function replicationStatus(creds, replicationId, callback) { var model = deepcopy(CONFIG.replicationStatus); model.ReplicationStatusRequest.ReplicationId = replicationId; httpClient.post('ReplicationStatus', model, function (res) { callback(res); }, creds); } //Analyze Replication function analyzeReplication(creds, replicationId, callback) { var model = deepcopy(CONFIG.analyzeReplication); model.AnalyzeReplicationRequest.ReplicationId = replicationId; httpClient.post('AnalyzeReplication', model, function (res) { callback(res); }, creds); } //Create Cluster function createCluster(creds, serverIP, serverCreds, callback) { var model = deepcopy(CONFIG.createCluster); model.CreateClusterRequest.RemoteServer = serverIP; model.CreateClusterRequest.PublicKey = serverCreds.accessKeyId; model.CreateClusterRequest.PrivateKey = serverCreds.secretAccessKey; httpClient.post('CreateCluster', model, function (res) { callback("Ok"); }, creds); } //Delete Cluster //StandaloneServer - Standalone server becomes primary. Schedules on the other server are inactivated. //The API call can be executed against the API of either of the cluster servers function deleteCluster(creds, serverIP, callback) { var model = deepcopy(CONFIG.deleteCluster); model.DeleteClusterRequest.StandaloneServer = serverIP; httpClient.post('DeleteCluster', model, function (res) { callback("Ok"); }, creds); } }
http-client.js
var http = require('http'), https = require('https'), aws4 = require('aws4'), xml2js = require('xml2js'), deepcopy = require("deepcopy"), CONFIG = require('./config.json'); function sign(opts, creds) { aws4.sign(opts, creds); } function createBody(model) { if (CONFIG.xml) { var builder = new xml2js.Builder({ explicitRoot: false, xmldec: { version: "1.0", encoding: "utf-8" } }); return builder.buildObject(model); } else { var body = firstPropToCamelCase(model); return body; } } //get first property of the model and translate first letter to lower case //skip ActivateInstanceRequest, DeleteReplicationRequest, ReplicationStatusRequest etc. function firstPropToCamelCase(obj) { return JSON.stringify(obj[Object.keys(obj)[0]], function (key, value) { if (value && typeof value === 'object') { var replacement = {}; for (var k in value) { if (Object.hasOwnProperty.call(value, k)) { replacement[k && k.charAt(0).toLowerCase() + k.substring(1)] = value[k]; } } return replacement; } return value; }); } function changeHost(host) { var options = CONFIG.options; options.host = host; } function createOptions(path) { var options = deepcopy(CONFIG.options); options.path = `${CONFIG.addOptions.basePath}${path}`; options.port = CONFIG.https ? CONFIG.addOptions.httpsPort : CONFIG.addOptions.httpPort; if (!CONFIG.xml) { options.headers["Content-Type"] = "application/json" } return options; } function post(path, model, callback, creds = undefined) { var options = createOptions(path); options.method = 'POST'; options.body = createBody(model); if (creds) { sign(options, creds); } return request(options, callback); }; function get(path, callback, creds = undefined) { var options = createOptions(path); if (creds) { sign(options, creds); } return request(options, callback); }; function request(options, callback) { var protocol = CONFIG.https ? https : http; var req = protocol.request(options, function (res) { var res, resJS; if (res.statusCode == 200) { res.setEncoding('utf8'); res.on('data', (res) => { if (CONFIG.xml) { var parser = new xml2js.Parser({ explicitArray: false }); parser.parseString(res, function (err, result) { resJS = JSON.parse(firstPropToCamelCase(result)); }); } else { resJS = JSON.parse(res); } }); res.on('end', function () { callback(resJS); }); } else { res.setEncoding('utf8'); res.on('data', (chunk) => { console.log(``); console.log(`Error: ${chunk}`); }); } }); req.write(options.body); req.end(); } module.exports = { post: post, get: get, changeHost: changeHost };
config.json
{ "xml": false, "https": true, "addOptions": { "httpPort": "82", "httpsPort": "4432", "basePath": "/api/" }, "options": { "host": "your.server1.IP.address", "port": "4432", "method": "GET", "service": "cloudbasic", "rejectUnauthorized": false, "headers": { "X-Amz-Content-Sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "Content-Type": "application/xml" }, "timeout": 120 }, "activateInstance": { "ActivateInstanceRequest": { "Email": "your_user@your_domain.com", "InstanceId": "i-011c1c1edd1111dc1", "Password": "YourPassword", "IsProduction": true, "Company": "test", "ContactPerson": "", "ActivationKey": "" } }, "createUser": { "CreateUserRequest": { "Email": "new_email@your_domain.com", "Username": "new_user", "FirstName": "New", "LastName": "User", "Password": "YourPassword", "IsAdmin": true } }, "createReplication": { "CreateReplicationRequest": { "ReplicationMethod": "ContinuousWithAutoSeeding", "ReplicateLoginsUsersAndRoles": false, "ReplicateTablesOnly": false, "ParallelTablesLimit": "5", "RebuildIndexes": false, "Source": { "ConnectionString": "Data Source=your.server.name;Initial Catalog=YourDatabaseName;Persist Security Info=False;User ID=YourUser;Password=YourPassword;Connect Timeout=1280", "EncryptDataInTransit": false, "ChangeTrackingRetentionPeriod": "2 DAYS", "ResetChangeTracking": false }, "Destination": { "ConnectionString": "Data Source=your.destination.server.name;Initial Catalog=YourDestinationDatabaseName;Persist Security Info=False;User ID=YourUser;Password=YourPassword;Connect Timeout=1280", "EncryptDataInTransit": false, "ReplicateCompatibilityLevel": true, "AzureServerTier": null, "AzureMaxDbSize": null, "CustomDbCreateScript": null, "PreSeedingCustomAction": null, "PostSeedingCustomAction": null } } }, "deleteReplication": { "DeleteReplicationRequest": { "ReplicationId": "" } }, "replicationStatus": { "ReplicationStatusRequest": { "ReplicationId": "" } }, "analyzeReplication": { "AnalyzeReplicationRequest": { "ReplicationId": "" } }, "createCluster": { "CreateClusterRequest": { "RemoteServer": "your.server2.IP.address", "Port": "81", "PublicKey": "YOUR.PUBLIC.KEY.ID", "PrivateKey": "YOUR.PRIVATE.KEY.VALUE" } }, "deleteCluster": { "DeleteClusterRequest": { "StandaloneServer": "" } } }