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": ""
}
}
}
