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)
(nothing yet)
- #65 Fix `triton profile(s)` handling when the user has no profiles yet.
## 3.4.1

View File

@ -188,13 +188,26 @@ function validateProfile(profile, profilePath) {
try {
assert.string(profile.name, 'profile.name');
assert.string(profile.url, 'profile.url');
assert.string(profile.account, 'profile.account');
assert.string(profile.keyId, 'profile.keyId');
assert.optionalBool(profile.insecure, 'profile.insecure');
assert.optionalString(profile.user, 'profile.user');
assert.string(profile.url,
profile.name === 'env' ? 'TRITON_URL or SDC_URL' : 'profile.url');
assert.string(profile.account,
profile.name === 'env' ? 'TRITON_ACCOUNT or SDC_ACCOUNT'
: '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) {
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 = [];
@ -219,7 +232,10 @@ function validateProfile(profile, profilePath) {
* However, per the "Environment variable integration" comment in cli.js, we
* 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() {
var envProfile = {
@ -233,6 +249,16 @@ function _loadEnvProfile() {
}
envProfile.url = process.env.TRITON_URL || process.env.SDC_URL;
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) {
envProfile.insecure = common.boolFromString(
process.env.TRITON_TLS_INSECURE);
@ -243,7 +269,7 @@ function _loadEnvProfile() {
envProfile.insecure = common.boolFromString(process.env.SDC_TESTING);
}
validateProfile(envProfile);
validateProfile(envProfile, 'environment variables');
return envProfile;
}
@ -294,32 +320,38 @@ function loadAllProfiles(opts) {
assert.string(opts.configDir, 'opts.configDir');
assert.object(opts.log, 'opts.log');
var profiles = [
_loadEnvProfile()
];
var profiles = [];
var envProfile = _loadEnvProfile();
if (envProfile) {
profiles.push(envProfile);
}
var d = path.join(common.tildeSync(opts.configDir), 'profiles.d');
var files = fs.readdirSync(d);
files.forEach(function (file) {
file = path.join(d, file);
var ext = path.extname(file);
if (ext !== '.json')
return;
if (fs.existsSync(d)) {
var files = fs.readdirSync(d);
files.forEach(function (file) {
file = path.join(d, file);
var ext = path.extname(file);
if (ext !== '.json')
return;
var name = path.basename(file).slice(0, - path.extname(file).length);
if (name.toLowerCase() === 'env') {
// Skip the special 'env'.
opts.log.warn({profilePath: file},
'invalid "env" profile; skipping');
return;
}
try {
profiles.push(_profileFromPath(file, name));
} catch (e) {
opts.log.warn({err: e, profilePath: file},
'error loading profile; skipping');
}
});
var name = path.basename(file).slice(
0, - path.extname(file).length);
if (name.toLowerCase() === 'env') {
// Skip the special 'env'.
opts.log.warn({profilePath: file},
'invalid "env" profile; skipping');
return;
}
try {
profiles.push(_profileFromPath(file, name));
} catch (e) {
opts.log.warn({err: e, profilePath: file},
'error loading profile; skipping');
}
});
}
return profiles;
}
@ -353,6 +385,9 @@ function saveProfileSync(opts) {
var profilePath = path.resolve(opts.configDir, 'profiles.d',
name + '.json');
if (!fs.existsSync(path.dirname(profilePath))) {
mkdirp.sync(path.dirname(profilePath));
}
fs.writeFileSync(profilePath, JSON.stringify(toSave, null, 4), 'utf8');
console.log('Saved profile "%s"', name);
}

View File

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