joyent/node-triton#65 Fix 'triton profile(s)' handling when the user has no profiles yet

This commit is contained in:
Trent Mick 2015-12-29 14:32:27 -08:00
parent baddfbf814
commit f66e50c770
3 changed files with 105 additions and 52 deletions

View File

@ -2,7 +2,7 @@
## 3.4.2 (not yet released) ## 3.4.2 (not yet released)
(nothing yet) - #65 Fix `triton profile(s)` handling when the user has no profiles yet.
## 3.4.1 ## 3.4.1

View File

@ -188,13 +188,26 @@ function validateProfile(profile, profilePath) {
try { try {
assert.string(profile.name, 'profile.name'); assert.string(profile.name, 'profile.name');
assert.string(profile.url, 'profile.url'); assert.string(profile.url,
assert.string(profile.account, 'profile.account'); profile.name === 'env' ? 'TRITON_URL or SDC_URL' : 'profile.url');
assert.string(profile.keyId, 'profile.keyId'); assert.string(profile.account,
assert.optionalBool(profile.insecure, 'profile.insecure'); profile.name === 'env' ? 'TRITON_ACCOUNT or SDC_ACCOUNT'
assert.optionalString(profile.user, 'profile.user'); : 'profile.account');
assert.string(profile.keyId,
profile.name === 'env' ? 'TRITON_KEY_ID or SDC_KEY_ID'
: 'profile.keyId');
assert.optionalBool(profile.insecure,
profile.name === 'env' ? 'TRITON_INSECURE or SDC_INSECURE'
: 'profile.insecure');
assert.optionalString(profile.user,
profile.name === 'env' ? 'TRITON_USER or SDC_USER'
: 'profile.user');
} catch (err) { } catch (err) {
throw new errors.ConfigError(err.message); var msg = format('invalid %sprofile%s: %s',
profile.name ? '"' + profile.name + '" ' : '',
profilePath ? ' from ' + profilePath: '',
err.message);
throw new errors.ConfigError(msg);
} }
var bogusFields = []; var bogusFields = [];
@ -219,7 +232,10 @@ function validateProfile(profile, profilePath) {
* However, per the "Environment variable integration" comment in cli.js, we * However, per the "Environment variable integration" comment in cli.js, we
* do that manually. * do that manually.
* *
* @returns {Object} The 'env' profile. * @returns {Object} The 'env' profile. If no relevant envvars are set, then
* this returns null.
* @throws {errors.ConfigError} If the profile defined by the environment is
* invalid.
*/ */
function _loadEnvProfile() { function _loadEnvProfile() {
var envProfile = { var envProfile = {
@ -233,6 +249,16 @@ function _loadEnvProfile() {
} }
envProfile.url = process.env.TRITON_URL || process.env.SDC_URL; envProfile.url = process.env.TRITON_URL || process.env.SDC_URL;
envProfile.keyId = process.env.TRITON_KEY_ID || process.env.SDC_KEY_ID; envProfile.keyId = process.env.TRITON_KEY_ID || process.env.SDC_KEY_ID;
/*
* If none of the above envvars are defined, then there is no env profile.
*/
if (!envProfile.account && !envProfile.user && !envProfile.url &&
!envProfile.keyId)
{
return null;
}
if (process.env.TRITON_TLS_INSECURE) { if (process.env.TRITON_TLS_INSECURE) {
envProfile.insecure = common.boolFromString( envProfile.insecure = common.boolFromString(
process.env.TRITON_TLS_INSECURE); process.env.TRITON_TLS_INSECURE);
@ -243,7 +269,7 @@ function _loadEnvProfile() {
envProfile.insecure = common.boolFromString(process.env.SDC_TESTING); envProfile.insecure = common.boolFromString(process.env.SDC_TESTING);
} }
validateProfile(envProfile); validateProfile(envProfile, 'environment variables');
return envProfile; return envProfile;
} }
@ -294,32 +320,38 @@ function loadAllProfiles(opts) {
assert.string(opts.configDir, 'opts.configDir'); assert.string(opts.configDir, 'opts.configDir');
assert.object(opts.log, 'opts.log'); assert.object(opts.log, 'opts.log');
var profiles = [ var profiles = [];
_loadEnvProfile()
]; var envProfile = _loadEnvProfile();
if (envProfile) {
profiles.push(envProfile);
}
var d = path.join(common.tildeSync(opts.configDir), 'profiles.d'); var d = path.join(common.tildeSync(opts.configDir), 'profiles.d');
var files = fs.readdirSync(d); if (fs.existsSync(d)) {
files.forEach(function (file) { var files = fs.readdirSync(d);
file = path.join(d, file); files.forEach(function (file) {
var ext = path.extname(file); file = path.join(d, file);
if (ext !== '.json') var ext = path.extname(file);
return; if (ext !== '.json')
return;
var name = path.basename(file).slice(0, - path.extname(file).length); var name = path.basename(file).slice(
if (name.toLowerCase() === 'env') { 0, - path.extname(file).length);
// Skip the special 'env'. if (name.toLowerCase() === 'env') {
opts.log.warn({profilePath: file}, // Skip the special 'env'.
'invalid "env" profile; skipping'); opts.log.warn({profilePath: file},
return; 'invalid "env" profile; skipping');
} return;
try { }
profiles.push(_profileFromPath(file, name)); try {
} catch (e) { profiles.push(_profileFromPath(file, name));
opts.log.warn({err: e, profilePath: file}, } catch (e) {
'error loading profile; skipping'); opts.log.warn({err: e, profilePath: file},
} 'error loading profile; skipping');
}); }
});
}
return profiles; return profiles;
} }
@ -353,6 +385,9 @@ function saveProfileSync(opts) {
var profilePath = path.resolve(opts.configDir, 'profiles.d', var profilePath = path.resolve(opts.configDir, 'profiles.d',
name + '.json'); name + '.json');
if (!fs.existsSync(path.dirname(profilePath))) {
mkdirp.sync(path.dirname(profilePath));
}
fs.writeFileSync(profilePath, JSON.stringify(toSave, null, 4), 'utf8'); fs.writeFileSync(profilePath, JSON.stringify(toSave, null, 4), 'utf8');
console.log('Saved profile "%s"', name); console.log('Saved profile "%s"', name);
} }

View File

@ -292,7 +292,18 @@ function _addProfile(opts, cb) {
var context; var context;
var data; var data;
vasync.pipeline({funcs: [ vasync.pipeline({arg: {}, funcs: [
function getExistingProfiles(ctx, next) {
try {
ctx.profiles = mod_config.loadAllProfiles({
configDir: cli.configDir,
log: cli.log
});
} catch (err) {
return next(err);
}
next();
},
function gatherDataStdin(_, next) { function gatherDataStdin(_, next) {
if (opts.file !== '-') { if (opts.file !== '-') {
return next(); return next();
@ -327,7 +338,7 @@ function _addProfile(opts, cb) {
} }
next(); next();
}, },
function gatherDataInteractive(_, next) { function gatherDataInteractive(ctx, next) {
if (opts.file) { if (opts.file) {
return next(); return next();
} else if (!process.stdin.isTTY) { } else if (!process.stdin.isTTY) {
@ -338,11 +349,6 @@ function _addProfile(opts, cb) {
'create profile: stdout is not a TTY')); 'create profile: stdout is not a TTY'));
} }
var profiles = mod_config.loadAllProfiles({
configDir: cli.configDir,
log: cli.log
});
var fields = [ { var fields = [ {
desc: 'A profile name. A short string to identify a ' + desc: 'A profile name. A short string to identify a ' +
'CloudAPI endpoint to the `triton` CLI.', 'CloudAPI endpoint to the `triton` CLI.',
@ -354,8 +360,8 @@ function _addProfile(opts, cb) {
'letter followed by lowercase letters, numbers ' + 'letter followed by lowercase letters, numbers ' +
'and "_", "." and "-".')); 'and "_", "." and "-".'));
} }
for (var i = 0; i < profiles.length; i++) { for (var i = 0; i < ctx.profiles.length; i++) {
if (profiles[i].name === value) { if (ctx.profiles[i].name === value) {
return valCb(new Error(format( return valCb(new Error(format(
'Profile "%s" already exists.', value))); 'Profile "%s" already exists.', value)));
} }
@ -438,17 +444,9 @@ function _addProfile(opts, cb) {
next(err); next(err);
}); });
}, },
function guardAlreadyExists(_, next) { function guardAlreadyExists(ctx, next) {
try { for (var i = 0; i < ctx.profiles.length; i++) {
var profiles = mod_config.loadAllProfiles({ if (data.name === ctx.profiles[i].name) {
configDir: cli.configDir,
log: cli.log
});
} catch (err) {
return next(err);
}
for (var i = 0; i < profiles.length; i++) {
if (data.name === profiles[i].name) {
return next(new errors.TritonError(format( return next(new errors.TritonError(format(
'profile "%s" already exists', data.name))); 'profile "%s" already exists', data.name)));
} }
@ -476,6 +474,26 @@ function _addProfile(opts, cb) {
return next(err); return next(err);
} }
next(); next();
},
function setCurrIfTheOnlyProfile(ctx, next) {
if (ctx.profiles.length !== 0) {
next();
return;
}
mod_config.setConfigVar({
configDir: cli.configDir,
name: 'profile',
value: data.name
}, function (err) {
if (err) {
next(err);
return;
}
console.log('Set "%s" as current profile (because it is ' +
'your only profile)', data.name);
next();
});
} }
]}, cb); ]}, cb);
} }