wire up Triton class and cloudapi client

This commit is contained in:
Trent Mick 2015-08-25 13:11:40 -07:00
parent 1f123975ae
commit d694f0ba19
4 changed files with 78 additions and 160 deletions

View File

@ -18,8 +18,7 @@ var vasync = require('vasync');
var common = require('./common');
var errors = require('./errors');
//XXX
//var SDC = require('./sdc');
var Triton = require('./triton');
@ -74,18 +73,28 @@ CLI.prototype.init = function (opts, args, callback) {
log.src = true;
}
//XXX
//this.__defineGetter__('sdc', function () {
// if (self._sdc === undefined) {
// self._sdc = new SDC({log: log, profile: opts.profile});
// }
// return self._sdc;
//});
this.__defineGetter__('triton', function () {
if (self._triton === undefined) {
self._triton = new Triton({log: log, profile: opts.profile});
}
return self._triton;
});
// Cmdln class handles `opts.help`.
Cmdln.prototype.init.apply(this, arguments);
};
CLI.prototype.do_foo = function do_foo(subcmd, opts, args, callback) {
console.log('XXX', subcmd, opts, args);
this.triton.cloudapi.getAccount(function (err, body, res) {
console.log('XXX getAccount', err);
console.log('XXX getAccount', body);
callback();
});
};
CLI.prototype.do_profile = require('./do_profile');

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
*
* Client library for the SmartDataCenter Cloud API (cloudapi).
* http://apidocs.joyent.com/cloudapi/
@ -27,12 +27,12 @@
var p = console.log;
var assert = require('assert-plus');
var async = require('async');
var auth = require('smartdc-auth');
var os = require('os');
var querystring = require('querystring');
var restify = require('restify');
var restifyClients = require('restify-clients');
var sprintf = require('util').format;
var vasync = require('vasync');
var errors = require('./errors');
@ -40,7 +40,7 @@ var errors = require('./errors');
// ---- globals
var SDC_VERSION = require('../package.json').version;
var VERSION = require('../package.json').version;
var OS_ARCH = os.arch();
var OS_PLATFORM = os.platform();
@ -105,8 +105,8 @@ function CloudAPI(options) {
options.version = '*';
}
if (!options.userAgent) {
options.userAgent = sprintf('sdc/%s (%s-%s; node/%s)',
SDC_VERSION, OS_ARCH, OS_PLATFORM, process.versions.node);
options.userAgent = sprintf('triton/%s (%s-%s; node/%s)',
VERSION, OS_ARCH, OS_PLATFORM, process.versions.node);
}
// XXX relevant?
@ -117,7 +117,7 @@ function CloudAPI(options) {
// XXX relevant?
//this.token = options.token;
this.client = restify.createJsonClient(options);
this.client = restifyClients.createJsonClient(options);
}

View File

@ -13,14 +13,13 @@ var common = require('./common');
var errors = require('./errors');
var CONFIG_PATH = path.resolve(process.env.HOME, '.sdcconfig.json');
var CONFIG_PATH = path.resolve(process.env.HOME, '.triton', 'config.json');
var DEFAULTS_PATH = path.resolve(__dirname, '..', 'etc', 'defaults.json');
var OVERRIDE_KEYS = ['dc', 'dcAlias'];
var OVERRIDE_KEYS = []; // config object keys to do a one-level deep override
/**
* Load the 'sdc' config. This is a merge of the built-in "defaults" (at
* etc/defaults.json) and the "user" config (at ~/.sdcconfig.json if it
* Load the Triton client config. This is a merge of the built-in "defaults" (at
* etc/defaults.json) and the "user" config (at ~/.triton/config.json if it
* exists).
*
* This includes some internal data on keys with a leading underscore.
@ -61,13 +60,13 @@ function loadConfigSync() {
if (!config.profiles) {
config.profiles = [];
}
//XXX Add TRITON_* envvars.
config.profiles.push({
name: 'env',
dcs: ['joyent'],
user: process.env.SDC_USER || process.env.SDC_ACCOUNT,
account: process.env.SDC_USER || process.env.SDC_ACCOUNT,
url: process.env.SDC_URL,
keyId: process.env.SDC_KEY_ID,
rejectUnauthorized: common.boolFromString(
process.env.SDC_TESTING || process.env.SDC_TLS_INSECURE)
insecure: common.boolFromString(process.env.SDC_TESTING)
});
return config;
@ -90,8 +89,6 @@ function updateUserConfigSync(config, updates) {
module.exports = {
CONFIG_PATH: CONFIG_PATH,
loadConfigSync: loadConfigSync,
//XXX
//updateConfigSync: updateConfigSync
loadConfigSync: loadConfigSync
};
// vim: set softtabstop=4 shiftwidth=4:

View File

@ -1,18 +1,17 @@
/*
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
*
* Core SDC driver class.
* Core Triton client driver class.
*/
var p = console.log;
var assert = require('assert-plus');
var async = require('async');
var auth = require('smartdc-auth');
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var once = require('once');
var path = require('path');
var restify = require('restify');
var restifyClients = require('restify-clients');
var sprintf = require('util').format;
var cloudapi = require('./cloudapi2');
@ -22,17 +21,17 @@ var loadConfigSync = require('./config').loadConfigSync;
//---- SDC class
//---- Triton class
/**
* Create a SDC client.
* Create a Triton client.
*
* @param options {Object}
* - log {Bunyan Logger}
* - profile {String} Optional. Name of profile to use. Defaults to
* 'defaultProfile' in the config.
*/
function SDC(options) {
function Triton(options) {
assert.object(options, 'options');
assert.object(options.log, 'options.log');
assert.optionalString(options.profile, 'options.profile');
@ -43,8 +42,10 @@ function SDC(options) {
if (options.log.serializers &&
(!options.log.serializers.client_req ||
!options.log.serializers.client_req)) {
console.log('XXX here');
this.log = options.log.child({
serializers: restify.bunyan.serializers
// XXX cheating. restify-clients should export its 'bunyan'.
serializers: require('restify-clients/lib/helpers/bunyan').serializers
});
} else {
this.log = options.log;
@ -54,20 +55,13 @@ function SDC(options) {
this.profile = this.getProfile(
options.profile || this.config.defaultProfile);
this.log.trace({profile: this.profile}, 'profile data');
this.cloudapi = this._cloudapiFromProfile(this.profile);
}
SDC.prototype.setDefaultProfile =
function setDefaultProfile(name, callback) {
if (!this.getProfile(name)) {
return callback(new Error('no such profile: ' + name));
}
this.defaultProfileName = this.config.defaultProfile = name;
common.saveConfigSync(this.config);
callback();
};
SDC.prototype.getProfile = function getProfile(name) {
Triton.prototype.getProfile = function getProfile(name) {
for (var i = 0; i < this.profiles.length; i++) {
if (this.profiles[i].name === name) {
return this.profiles[i];
@ -75,121 +69,39 @@ SDC.prototype.getProfile = function getProfile(name) {
}
};
/**
* Create or update a profile.
*
* @param profile {Object}
* @param options {Object}
* - setDefault {Boolean}
* @param callback {Function} `function (err)`
*/
SDC.prototype.createOrUpdateProfile = function createOrUpdateProfile(
profile, options, callback) {
Triton.prototype._cloudapiFromProfile = function _cloudapiFromProfile(profile) {
assert.object(profile, 'profile');
if (typeof (options) === 'function') {
callback = options;
options = {};
}
assert.object(options, 'options');
assert.optionalBool(options.setDefault, 'options.setDefault');
assert.func(callback, 'callback');
assert.string(profile.account, 'profile.account');
assert.string(profile.keyId, 'profile.keyId');
assert.string(profile.url, 'profile.url');
assert.optionalString(profile.privKey, 'profile.privKey');
assert.optionalBool(profile.insecure, 'profile.insecure');
var rejectUnauthorized = (profile.insecure === undefined
? true : !profile.insecure);
var found = false;
for (var i = 0; i < this.profiles.length; i++) {
if (this.profiles[i].name === profile.name) {
this.profiles[i] = profile;
found = true;
}
}
if (!found) {
this.profiles.push(profile);
}
if (options.setDefault) {
this.defaultProfileName = this.config.defaultProfile = profile.name;
}
common.saveConfigSync(this.config);
callback();
};
SDC.prototype.deleteProfile = function deleteProfile(name, callback) {
var found = false;
for (var i = 0; i < this.profiles.length; i++) {
if (this.profiles[i].name === name) {
found = true;
this.profiles.splice(i, 1);
}
}
if (!found) {
return callback(new Error('no such profile: ' + name));
}
if (this.defaultProfileName === name) {
this.defaultProfileName = this.config.defaultProfile = null;
}
common.saveConfigSync(this.config);
callback();
};
SDC.prototype._clientFromDc = function _clientFromDc(dc) {
assert.string(dc, 'dc');
if (!this._clientFromDcCache) {
this._clientFromDcCache = {};
}
if (!this._clientFromDcCache[dc]) {
var prof = this.profile;
var sign;
if (prof.privKey) {
sign = auth.privateKeySigner({
user: prof.user,
keyId: prof.keyId,
key: prof.privKey
});
} else {
sign = auth.cliSigner({
keyId: prof.keyId,
user: prof.user
});
}
var client = cloudapi.createClient({
url: this.config.dcs[dc],
user: prof.user,
version: '*',
rejectUnauthorized: Boolean(prof.rejectUnauthorized),
sign: sign,
log: this.log
var sign;
if (profile.privKey) {
sign = auth.privateKeySigner({
user: profile.account,
keyId: profile.keyId,
key: profile.privKey
});
this._clientFromDcCache[dc] = client;
}
return this._clientFromDcCache[dc];
};
/**
* Return the resolved array of `{name: <dc-name>, url: <dc-url>}` for all
* DCs for the current profile.
*
* @throws {Error} If an unknown DC name is encountered.
* XXX make that UnknownDcError.
*/
SDC.prototype.dcs = function dcs() {
var self = this;
var aliases = self.config.dcAlias || {};
var resolved = [];
(self.profile.dcs || Object.keys(self.config.dcs)).forEach(function (n) {
var names = aliases[n] || [n];
names.forEach(function (name) {
if (!self.config.dcs[name]) {
throw new Error(sprintf('unknown dc "%s" for "%s" profile',
name, self.profile.name));
}
resolved.push({
name: name,
url: self.config.dcs[name]
});
} else {
sign = auth.cliSigner({
keyId: profile.keyId,
user: profile.account
});
}
var client = cloudapi.createClient({
url: profile.url,
user: profile.account,
version: '*',
rejectUnauthorized: rejectUnauthorized,
sign: sign,
log: this.log
});
return resolved;
return client;
};
@ -204,7 +116,7 @@ SDC.prototype.dcs = function dcs() {
* Returns the machine object (as from cloudapi GetMachine) and the `dc`,
* e.g. "us-west-1".
*/
SDC.prototype.findMachine = function findMachine(options, callback) {
Triton.prototype.findMachine = function findMachine(options, callback) {
//XXX Eventually this can be cached for a *full* uuid. Arguably for a
// uuid prefix or machine alias match, it cannot be cached, because an
// ambiguous machine could have been added.
@ -267,7 +179,7 @@ SDC.prototype.findMachine = function findMachine(options, callback) {
*
* @param {Object} options Optional
*/
SDC.prototype.listMachines = function listMachines(options) {
Triton.prototype.listMachines = function listMachines(options) {
var self = this;
if (options === undefined) {
options = {};
@ -304,7 +216,7 @@ SDC.prototype.listMachines = function listMachines(options) {
* XXX support `machine` being more than just the UUID.
* @param {Function} callback of the form `function (err, audit, dc)`
*/
SDC.prototype.machineAudit = function machineAudit(options, callback) {
Triton.prototype.machineAudit = function machineAudit(options, callback) {
var self = this;
assert.object(options, 'options');
assert.string(options.machine, 'options.machine');
@ -324,4 +236,4 @@ SDC.prototype.machineAudit = function machineAudit(options, callback) {
//---- exports
module.exports = SDC;
module.exports = Triton;