joyent/node-triton#137 triton CLI tool fails in default usecase
Reviewed by: Chris Burroughs <chris.burroughs@joyent.com> Approved by: Chris Burroughs <chris.burroughs@joyent.com>
This commit is contained in:
parent
2453bc12e8
commit
3a369e4bb8
@ -7,6 +7,9 @@ Known issues:
|
||||
|
||||
## not yet released
|
||||
|
||||
- [joyent/node-triton#137] Improve the handling for the getting started case
|
||||
when a user may not have envvars or a profile setup.
|
||||
|
||||
- [joyent/node-triton#158] tritonapi image cache never expires
|
||||
|
||||
- [joyent/node-triton#153] Bump restify-clients dep. Thanks, github.com/tomgco.
|
||||
|
62
README.md
62
README.md
@ -46,20 +46,66 @@ Have the URL handy as you'll need it in the next step.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Install [node.js](http://nodejs.org/).
|
||||
2. `npm install -g triton`
|
||||
Install [node.js](http://nodejs.org/), then:
|
||||
|
||||
npm install -g triton
|
||||
|
||||
Verify that it is installed and on your PATH:
|
||||
|
||||
$ triton --version
|
||||
Triton CLI 1.0.0
|
||||
Triton CLI 4.15.0
|
||||
https://github.com/joyent/node-triton
|
||||
|
||||
Configure the proper environmental variables that correspond to the API endpoint and account,
|
||||
for example:
|
||||
To use `triton`, you'll need to configure it to talk to a Triton DataCenter
|
||||
API endpoint (called CloudAPI). Commonly that is done using a Triton profile:
|
||||
|
||||
SDC_URL=https://us-east-3b.api.joyent.com
|
||||
SDC_ACCOUNT=dave.eddy@joyent.com
|
||||
SDC_KEY_ID=04:0c:22:25:c9:85:d8:e4:fa:27:0d:67:94:68:9e:e9
|
||||
$ triton profile create
|
||||
A profile name. A short string to identify a CloudAPI endpoint to the
|
||||
`triton` CLI.
|
||||
name: sw1
|
||||
|
||||
The CloudAPI endpoint URL.
|
||||
url: https://us-sw-1.api.joyent.com
|
||||
|
||||
Your account login name.
|
||||
account: bob
|
||||
|
||||
Available SSH keys:
|
||||
1. 2048-bit RSA key with fingerprint 4e:e7:56:9a:b0:91:31:3e:23:8d:f8:62:12:58:a2:ec
|
||||
* [in homedir] bob-20160704 id_rsa
|
||||
|
||||
The fingerprint of the SSH key you want to use, or its index in the list
|
||||
above. If the key you want to use is not listed, make sure it is either saved
|
||||
in your SSH keys directory or loaded into the SSH agent.
|
||||
keyId: 1
|
||||
|
||||
Saved profile "sw1".
|
||||
|
||||
WARNING: Docker uses TLS-based authentication with a different security model
|
||||
from SSH keys. As a result, the Docker client cannot currently support
|
||||
encrypted (password protected) keys or SSH agents. If you continue, the
|
||||
Triton CLI will attempt to format a copy of your SSH *private* key as an
|
||||
unencrypted TLS cert and place the copy in ~/.triton/docker for use by the
|
||||
Docker client.
|
||||
Continue? [y/n] y
|
||||
Setting up profile "sw1" to use Docker.
|
||||
Setup profile "sw1" to use Docker (v1.12.3). Try this:
|
||||
eval "$(triton env --docker sw1)"
|
||||
docker info
|
||||
|
||||
Set "sw1" as current profile (because it is your only profile).
|
||||
|
||||
Or instead of using profiles, you can set the required environment variables
|
||||
(`triton` defaults to an "env" profile that uses these environment variables if
|
||||
no profile is set). For example:
|
||||
|
||||
TRITON_URL=https://us-sw-1.api.joyent.com
|
||||
TRITON_ACCOUNT=bob
|
||||
TRITON_KEY_ID=SHA256:j2WoSeOWhFy69BQ0uCR3FAySp9qCZTSCEyT2vRKcL+s
|
||||
|
||||
For compatibility with the older [sdc-* tools from
|
||||
node-smartdc](https://github.com/joyent/node-smartdc), `triton` also supports
|
||||
`SDC_URL`, `SDC_ACCOUNT`, etc. environment variables.
|
||||
|
||||
|
||||
### Bash completion
|
||||
|
78
lib/cli.js
78
lib/cli.js
@ -25,6 +25,7 @@ var path = require('path');
|
||||
var vasync = require('vasync');
|
||||
|
||||
var common = require('./common');
|
||||
var constants = require('./constants');
|
||||
var mod_config = require('./config');
|
||||
var errors = require('./errors');
|
||||
var lib_tritonapi = require('./tritonapi');
|
||||
@ -35,21 +36,6 @@ var lib_tritonapi = require('./tritonapi');
|
||||
|
||||
var packageJson = require('../package.json');
|
||||
|
||||
var CONFIG_DIR;
|
||||
if (process.platform === 'win32') {
|
||||
/*
|
||||
* For better or worse we are using APPDATA (i.e. the *Roaming* AppData
|
||||
* dir) over LOCALAPPDATA (non-roaming). The former is meant for "user"
|
||||
* data, the latter for "machine" data.
|
||||
*
|
||||
* TODO: We should likely separate out the *cache* subdir to
|
||||
* machine-specific data dir.
|
||||
*/
|
||||
CONFIG_DIR = path.resolve(process.env.APPDATA, 'Joyent', 'Triton');
|
||||
} else {
|
||||
CONFIG_DIR = path.resolve(process.env.HOME, '.triton');
|
||||
}
|
||||
|
||||
|
||||
var OPTIONS = [
|
||||
{
|
||||
@ -262,7 +248,8 @@ CLI.prototype.init = function (opts, args, callback) {
|
||||
}
|
||||
|
||||
if (opts.version) {
|
||||
console.log(this.name, packageJson.version);
|
||||
console.log('Triton CLI', packageJson.version);
|
||||
console.log(packageJson.homepage);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
@ -274,7 +261,7 @@ CLI.prototype.init = function (opts, args, callback) {
|
||||
opts.url = format('https://%s.api.joyent.com', opts.J);
|
||||
}
|
||||
|
||||
this.configDir = CONFIG_DIR;
|
||||
this.configDir = constants.CLI_CONFIG_DIR;
|
||||
|
||||
this.__defineGetter__('config', function getConfig() {
|
||||
if (self._config === undefined) {
|
||||
@ -292,26 +279,48 @@ CLI.prototype.init = function (opts, args, callback) {
|
||||
|
||||
this.__defineGetter__('profile', function getProfile() {
|
||||
if (self._profile === undefined) {
|
||||
self._profile = mod_config.loadProfile({
|
||||
configDir: self.configDir,
|
||||
name: self.profileName
|
||||
});
|
||||
try {
|
||||
self._profile = mod_config.loadProfile({
|
||||
configDir: self.configDir,
|
||||
name: self.profileName
|
||||
});
|
||||
} catch (pErr) {
|
||||
/*
|
||||
* Let's be nice for the getting started use case where we
|
||||
* defaulted to 'env' profile (e.g. the user has never created
|
||||
* one) and the minimal envvars aren't set. I.e. The user just
|
||||
* installed and ran `triton ls` or some other command.
|
||||
*/
|
||||
if (pErr.code === 'Config' && self.profileName === 'env' &&
|
||||
!opts.profile && !self.config.profile)
|
||||
{
|
||||
/* BEGIN JSSTYLED */
|
||||
pErr.message += '\n'
|
||||
+ ' No profile information could be loaded.\n'
|
||||
+ ' Use "triton profile create" to create a profile or provide\n'
|
||||
+ ' the required "CloudAPI options" described in "triton --help".\n'
|
||||
+ ' See https://github.com/joyent/node-triton#setup for more help.';
|
||||
/* END JSSTYLED */
|
||||
}
|
||||
throw pErr;
|
||||
}
|
||||
self._applyProfileOverrides(self._profile);
|
||||
self.log.trace({profile: self._profile}, 'loaded profile');
|
||||
}
|
||||
return self._profile;
|
||||
});
|
||||
|
||||
try {
|
||||
self.tritonapi = lib_tritonapi.createClient({
|
||||
log: self.log,
|
||||
profile: self.profile,
|
||||
config: self.config
|
||||
});
|
||||
} catch (createErr) {
|
||||
callback(createErr);
|
||||
return;
|
||||
}
|
||||
this.__defineGetter__('tritonapi', function getTritonapi() {
|
||||
if (self._tritonapi === undefined) {
|
||||
self._tritonapi = lib_tritonapi.createClient({
|
||||
log: self.log,
|
||||
profile: self.profile,
|
||||
config: self.config
|
||||
});
|
||||
self.log.trace('created tritonapi');
|
||||
}
|
||||
return self._tritonapi;
|
||||
});
|
||||
|
||||
if (process.env.TRITON_COMPLETE) {
|
||||
/*
|
||||
@ -338,9 +347,9 @@ CLI.prototype.init = function (opts, args, callback) {
|
||||
|
||||
CLI.prototype.fini = function fini(subcmd, err, cb) {
|
||||
this.log.trace({err: err, subcmd: subcmd}, 'cli fini');
|
||||
if (this.tritonapi) {
|
||||
this.tritonapi.close();
|
||||
delete this.tritonapi;
|
||||
if (this._tritonapi) {
|
||||
this._tritonapi.close();
|
||||
delete this._tritonapi;
|
||||
}
|
||||
cb();
|
||||
};
|
||||
@ -732,7 +741,6 @@ function main(argv) {
|
||||
//---- exports
|
||||
|
||||
module.exports = {
|
||||
CONFIG_DIR: CONFIG_DIR,
|
||||
CLI: CLI,
|
||||
main: main
|
||||
};
|
||||
|
@ -314,7 +314,7 @@ function _createProfile(opts, cb) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
console.log('Set "%s" as current profile (because it is ' +
|
||||
console.log('\nSet "%s" as current profile (because it is ' +
|
||||
'your only profile).', data.name);
|
||||
next();
|
||||
});
|
||||
|
@ -80,7 +80,9 @@ function _listProfiles(cli, opts, args, cb) {
|
||||
if (!haveCurr) {
|
||||
if (profiles.length === 0) {
|
||||
process.stderr.write('\nWarning: There is no current profile. '
|
||||
+ 'Use "triton profile create" to create one.\n');
|
||||
+ 'Use "triton profile create" to create one,\n'
|
||||
+ 'or set the required "SDC_*/TRITON_*" environment '
|
||||
+ 'variables: see "triton --help".\n');
|
||||
} else {
|
||||
process.stderr.write('\nWarning: There is no current profile. '
|
||||
+ 'Use "triton profile set-current ..."\n'
|
||||
|
@ -166,7 +166,8 @@ function profileDockerSetup(opts, cb) {
|
||||
'Docker client.'));
|
||||
common.promptYesNo({msg: 'Continue? [y/n] '}, function (answer) {
|
||||
if (answer !== 'y') {
|
||||
console.error('Aborting');
|
||||
console.error('Skipping Docker setup (you can run '
|
||||
+ '"triton profile docker-setup" later).');
|
||||
next(true);
|
||||
} else {
|
||||
next();
|
||||
|
@ -3,6 +3,7 @@
|
||||
"description": "Joyent Triton CLI and client (https://www.joyent.com/triton)",
|
||||
"version": "4.15.0",
|
||||
"author": "Joyent (joyent.com)",
|
||||
"homepage": "https://github.com/joyent/node-triton",
|
||||
"dependencies": {
|
||||
"assert-plus": "0.2.0",
|
||||
"backoff": "2.4.1",
|
||||
@ -24,7 +25,7 @@
|
||||
"sshpk": "1.10.1",
|
||||
"sshpk-agent": "1.4.2",
|
||||
"strsplit": "1.0.0",
|
||||
"tabula": "1.7.0",
|
||||
"tabula": "1.9.0",
|
||||
"vasync": "1.6.3",
|
||||
"verror": "1.6.0",
|
||||
"which": "1.2.4",
|
||||
|
Reference in New Issue
Block a user