From d694f0ba19f1cea12a2dec51237790a7208df227 Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Tue, 25 Aug 2015 13:11:40 -0700 Subject: [PATCH] wire up Triton class and cloudapi client --- lib/cli.js | 27 ++++-- lib/cloudapi2.js | 14 +-- lib/config.js | 21 ++--- lib/{sdc.js => triton.js} | 176 ++++++++++---------------------------- 4 files changed, 78 insertions(+), 160 deletions(-) rename lib/{sdc.js => triton.js} (57%) diff --git a/lib/cli.js b/lib/cli.js index 9e63f29..3a83b4a 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -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'); diff --git a/lib/cloudapi2.js b/lib/cloudapi2.js index 5436378..79800be 100644 --- a/lib/cloudapi2.js +++ b/lib/cloudapi2.js @@ -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); } diff --git a/lib/config.js b/lib/config.js index e527f1c..1b80b5a 100755 --- a/lib/config.js +++ b/lib/config.js @@ -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: diff --git a/lib/sdc.js b/lib/triton.js similarity index 57% rename from lib/sdc.js rename to lib/triton.js index ab25a5a..81eec2d 100644 --- a/lib/sdc.js +++ b/lib/triton.js @@ -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: , 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;