tooltwist
Version:
Tooltwist Command Line Interface
370 lines (316 loc) • 10.7 kB
JavaScript
var DigitalOceanAPI = require('digitalocean-api'),
Templates = require('./templates'),
Mustache = require("mustache"),
Log = require('./log'),
fs = require('fs'),
path = require('path'),
os = require("os"),
printf = require('printf');
// Create an instance with your API credentials
var api = new DigitalOceanAPI('GmRxy2PfPFB7KuubUj7yN', '9a64d5965136c28c15a28aac9335c84b');
//5039e5b5a9fd05e5d663232505103c099d1fe2f31cf5e483e94ee86425fe39b5
function showDroplets(callback){
api.dropletGetAll(function(error, result){
console.log("\nDROPLETS:")
if (result) {
// console.log(result);
console.log(printf("%9s %-20s %-7s %-18s %7s %5s %7s %s", 'ID', 'NAME', 'STATUS', 'IP ADDR', 'IMAGE', 'SIZE', 'REGION', 'CREATED'))
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %-20s %-7s %-18s %7d %5d %7d %s", rec.id, rec.name, rec.status, rec.ip_address, rec.image_id, rec.size_id, rec.region_id, rec.created_at))
}
callback(null)
} else {
console.log(' could not get droplet information')
callback(new Error('Could not get droplet information'))
}
});
}
function showImages(callback){
api.imageGetAll(function(error, result){
console.log("\nIMAGES:")
if (result) {
// console.log(result);
// { id: 4991187,
// name: 'WordPress on Ubuntu 14.04',
// slug: null,
// distribution: 'Ubuntu',
// public: true,
// regions: [ 1, 2, 3, 4, 5, 6, 7, 8 ],
// region_slugs: [ 'nyc1', 'ams1', 'sfo1', 'nyc2', 'ams2', 'sgp1', 'lon1', 'nyc3' ] } ]
console.log(printf("%9s %6s %s", 'ID', 'PUBLIC', 'NAME'))
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %6s %s", rec.id, rec.public, rec.name))
}
callback(null)
} else {
console.log(' could not get images information')
callback(new Error('Could not get images information'))
}
});
}
function getUniqueDropletName(basename, callback){
api.imageGetAll(function(err, result){
if (err) return callback(err);
// Find the next sequence number with this prefix
var prefix = basename + '-';
var max = 1;
for (var i = 0; i < result.length; i++) {
var name = result[i].name;
if (name.indexOf(prefix) === 0) {
var suffix = name.substring(prefix.length);
try {
var num = parseInt(suffix)
if (num >= max) {
max = num + 1;
}
} catch (e) {
// Do nothing
}
}
}
// console.log('NEXT IN SEQUENCE=' + max)
return callback(null, prefix + max)
});
}
function showSizes(callback){
api.sizeGetAll(function(error, result){
console.log("\nSIZES:")
if (result) {
// console.log(result);
// { id: 60,
// name: '32GB',
// slug: '32gb',
// memory: 32768,
// cpu: 12,
// disk: 320,
// cost_per_hour: 0.47619,
// cost_per_month: '320.0' },
console.log(printf("%9s %-10s %5s %5s %6s %6s", 'ID', 'NAME', 'CPU', 'DISK', 'HOUR', 'MONTH'))
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %-10s %5d %5d %6.4f %6.2f", rec.id, rec.name, rec.cpu, rec.disk, rec.cost_per_hour, rec.cost_per_month))
}
callback(null)
} else {
console.log(' could not get size information')
callback(new Error('Could not get size information'))
}
});
}
function showSizes(callback){
api.sizeGetAll(function(error, result){
console.log("\nSIZES:")
if (result) {
// console.log(result);
// { id: 60,
// name: '32GB',
// slug: '32gb',
// memory: 32768,
// cpu: 12,
// disk: 320,
// cost_per_hour: 0.47619,
// cost_per_month: '320.0' },
console.log(printf("%9s %-10s %5s %5s %6s %6s", 'ID', 'NAME', 'CPU', 'DISK', 'HOUR', 'MONTH'))
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %-10s %5d %5d %6.4f %6.2f", rec.id, rec.name, rec.cpu, rec.disk, rec.cost_per_hour, rec.cost_per_month))
}
callback(null)
} else {
console.log(' could not get size information')
callback(new Error('Could not get size information'))
}
});
}
function showSshKeys(callback){
api.sshKeyGetAll(function(error, result){
console.log("\nSSH Keys:")
if (result) {
console.log(result);
// { id: 18237, name: 'Phil MBP' }
console.log(printf("%9s %s", 'ID', 'NAME'))
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %s", rec.id, rec.name))
}
callback(null)
} else {
console.log(' could not get SSH Key information')
callback(new Error('Could not get SSH Key information'))
}
});
}
function getAdminSshKey(publicKey, callback){
// Look for a key named 'admin'.
// Failing that, look for any key.
var ADMIN_KEY = 'admin';
api.sshKeyGetAll(function(error, result){
console.log("\nSSH Keys:")
if (result) {
console.log(result);
// { id: 18237, name: 'Phil MBP' }
console.log(printf("%9s %s", 'ID', 'NAME'))
var anyKey = null;
for (var i = 0; i < result.length; i++) {
var rec = result[i];
console.log(printf("%9d %s", rec.id, rec.name))
if (rec.name.toLowerCase() === ADMIN_KEY) {
// Found admin key
Log.info("Found SSH Key " + ADMIN_KEY)
return callback(rec);
}
// Remember the first key
if (anyKey == null) {
anyKey = rec;
}
}
// If we found any SSH key, return it now.
if (anyKey) {
console.log("RETURN ANY KEY")
return callback(anyKey);
}
// Need to create a new admin key
Log.info("Adding SSH Key " + ADMIN_KEY)
api.sshKeyAdd(ADMIN_KEY, publicKey, function(err, result){
if (err) {
Log.fatalError('Could not create SSH Key ' + ADMIN_KEY)
}
// console.log("After adding key: ", err, result)
callback(result)
});
} else {
console.log(' could not get SSH Key information')
callback(new Error('Could not get SSH Key information'))
}
});
}
function createDroplet(name, adminSshKeyId, callback) {
var sizeId = 66;
var imageId = 5505824; // node-v0.10.30 on Ubuntu 14.04
var imageId = 5736991; // Tooltwist
var regionId = 6;
var optionals = {
ssh_key_ids: [ adminSshKeyId ],
// private_networking: false,
// backups_enabled: false
};
api.dropletNew(name, sizeId, imageId, regionId, optionals, callback);
}
/**
* Wait for a droplet to start.
*/
function waitForServer(dropletId, endTime, callback){
if (endTime <= 0) {
endTime = Math.round(new Date().getTime() / 1000)
endTime += 120; // Allow 2 minutes for startup.
}
var now = Math.round(new Date().getTime() / 1000)
//console.log('waitForServer ', now, endTime)
if (now >= endTime) {
console.log('Timeout waiting for server to start')
return callback(null, false);
}
api.dropletGet(dropletId, function(err, result){
if (err) return callback(err, false);
// See if the status is now active
//console.log('result=', err, result);
//console.log('status is ' + result.status)
if (result.status === 'active') {
return callback(null, true);
} else if (result.status !== 'new') {
console.log('server has status ' + result.status)
callback(null, false);
}
//console.log('waiting...')
setTimeout(function(){
waitForServer(dropletId, endTime, callback)
}, 5000); // 5 seconds
})
}
exports.createServer = function(callback) {
Log.debug("digital-ocean.createServer()")
// Prepare the script we'll send to the server
var publicKey = getPublicKey();
var sourceUUID = createUUID();
var destinationUUID = createUUID();
var passphrase = "Chicken sickle marmalade toebar";
var username = process.env['USER'];
var hostname = os.hostname();
Log.info('publicKey=' + publicKey)
Log.info('sourceUUID=' + sourceUUID)
Log.info('destinationUUID=' + destinationUUID)
Log.info('passphrase=' + passphrase)
Log.info('username=' + username)
Log.info('hostname=' + hostname)
// Load the template
var view = {
PUBLIC_KEY: publicKey,
SOURCE_UUID: sourceUUID,
DESTINATION_UUID: destinationUUID,
PASSPHRASE: passphrase
};
var defaultTemplateDir = Config.RESOURCES_DIR + '/templates';
var from = Templates.findTemplate(defaultTemplateDir, 'install/template.prepareRemoteServer.sh');
var template = fs.readFileSync(from, "utf8");
var content = Mustache.render(template, view);
console.log('script is: ' + content)
// Find an SSH key to use
getAdminSshKey(publicKey, function(rec){
Log.info('Using SSH key ' + rec.name)
var adminSshKeyId = rec.id;
console.log("KEYYYYY ISSSSS ", rec)
// Base the server name on the current directory name
var name = path.basename(process.cwd());
// Find a name to use
getUniqueDropletName(name, function(err, newName){
console.log('Creating a droplet named \'' + newName + '\'.')
// Create a new droplet
createDroplet(newName, adminSshKeyId, function(err, result){
// console.log('createDroplet returned ', err, result)
if (err) return callback(err);
var dropletId = result.id;
// Wait for droplet to start.
console.log('\nWaiting for server to start...')
waitForServer(dropletId, 0, function(err, isReady) {
if (err) return callback(err);
if (!isReady) return callback(null, null); // Something went wrong
// Get details (including IP Address)
api.dropletGet(dropletId, function(err, dropletDetails){
// Return the details of the new server.
//console.log('dropletDetails:', dropletDetails)
return callback(null, isReady ? dropletDetails : null);
});
}); // waitForServer
}); // createDroplet
}); // getUniqueDropletName
}); // getAdminSshKey
showImages(function(){
})
}
/**
* Get the first line of ~/.ssh/id_rsa.pub
*/
function getPublicKey() {
var home = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
var path = home + "/.ssh/id_rsa.pub";
if ( !fs.existsSync(path)) {
Log.error()
Log.error('\tSorry, you\'ll need to have a ~/.ssh/id_rsa.pub before running this command.')
Log.error()
process.exit(1)
}
var keys = fs.readFileSync(path, "utf8");
// console.log('keys=' + keys);
var pos = keys.indexOf('\n');
var key = (pos < 0) ? keys : keys.substring(0, pos);
// console.log('key=' + key + '<');
return key;
}
/**
* Return a universally unique ID that can be used to identify a FIP source or destination.
*/
function createUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*36|0,v=c=='x'?r:r&0x3|0x8;return v.toString(36);});
}