Windows path fixes (should basically run on windows now)

Fixes #83.
This commit is contained in:
Trent Mick 2016-01-28 13:30:11 -08:00
parent 666b541e42
commit 54923c9ae3
11 changed files with 104 additions and 92 deletions

View File

@ -2,7 +2,9 @@
## 4.4.1 (not yet released) ## 4.4.1 (not yet released)
(nothing yet) - #83, #84 Fix running `triton` on Windows.
Note: Triton config is stored in "%APPDATA%/Joyent/Triton/..." on Windows,
"~/.triton/..." on other platforms.
## 4.4.0 ## 4.4.0

View File

@ -64,7 +64,8 @@ for example:
Install Bash completion with Install Bash completion with
```bash ```bash
triton completion > /usr/local/etc/bash_completion.d/triton triton completion > /usr/local/etc/bash_completion.d/triton # Mac
triton completion > /etc/bash_completion.d/triton # Linux
``` ```
Alternatively, if you don't have or don't want to use a "bash\_completion.d" Alternatively, if you don't have or don't want to use a "bash\_completion.d"
@ -258,7 +259,7 @@ A basic example:
This section defines all the vars in a TritonApi config. The baked in defaults This section defines all the vars in a TritonApi config. The baked in defaults
are in "etc/defaults.json" and can be overriden for the CLI in are in "etc/defaults.json" and can be overriden for the CLI in
"~/.triton/config.json". "~/.triton/config.json" (on Windows: "%APPDATA%/Joyent/Triton/config.json").
| Name | Description | | Name | Description |
| ---- | ----------- | | ---- | ----------- |

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright 2015 Joyent, Inc. * Copyright 2016 Joyent, Inc.
* *
* The `triton` CLI class. * The `triton` CLI class.
*/ */
@ -34,7 +34,21 @@ var tritonapi = require('./tritonapi');
var pkg = require('../package.json'); var pkg = require('../package.json');
var CONFIG_DIR = path.resolve(process.env.HOME, '.triton'); 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 = [ var OPTIONS = [
{ {

View File

@ -855,19 +855,24 @@ function deepEqual(a, b) {
/** /**
* Resolve "~/..." and "~" to an absolute path. * Resolve "~/..." and "~" to an absolute path.
* *
* Limitations: This does not handle "~user/...". This depends on the HOME * Limitations:
* envvar being defined. A better alternative is the "tilde-expansion" * - This does not handle "~user/...".
* module (used elsewhere in node-triton), but that doesn't have a sync * - This depends on the HOME envvar being defined (%USERPROFILE% on Windows).
* option.
*/ */
function tildeSync(s) { function tildeSync(s) {
var home = process.env.HOME; var envvar = (process.platform === 'win32' ? 'USERPROFILE' : 'HOME');
var home = process.env[envvar];
if (!home) { if (!home) {
return s; throw new Error(format('cannot determine home dir: %s environment ' +
} else if (s === '~') { 'variable is not defined', envvar));
}
if (s === '~') {
return home; return home;
} else if (s.slice(0, 2) === '~/') { } else if (s.slice(0, 2) === '~/' ||
return home + s.slice(1); (process.platform === 'win32' && s.slice(0, 2) === '~'+path.sep))
{
return path.resolve(home, s.slice(2));
} else { } else {
return s; return s;
} }

View File

@ -9,7 +9,6 @@ var format = require('util').format;
var fs = require('fs'); var fs = require('fs');
var strsplit = require('strsplit'); var strsplit = require('strsplit');
var sshpk = require('sshpk'); var sshpk = require('sshpk');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('./common'); var common = require('./common');

View File

@ -15,7 +15,6 @@ var format = require('util').format;
var fs = require('fs'); var fs = require('fs');
var strsplit = require('strsplit'); var strsplit = require('strsplit');
var tabula = require('tabula'); var tabula = require('tabula');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('../common'); var common = require('../common');

View File

@ -8,7 +8,6 @@ var assert = require('assert-plus');
var format = require('util').format; var format = require('util').format;
var fs = require('fs'); var fs = require('fs');
var sshpk = require('sshpk'); var sshpk = require('sshpk');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('../common'); var common = require('../common');
@ -168,29 +167,28 @@ function _createProfile(opts, cb) {
} }
// Try as a local path. // Try as a local path.
tilde(value, function (keyPath) { var keyPath = common.tildeSync(value);
fs.stat(keyPath, function (statErr, stats) { fs.stat(keyPath, function (statErr, stats) {
if (statErr || !stats.isFile()) { if (statErr || !stats.isFile()) {
return valCb(new Error(format( return valCb(new Error(format(
'"%s" is neither a valid fingerprint, ' + '"%s" is neither a valid fingerprint, ' +
'nor an existing file', value))); 'nor an existing file', value)));
}
fs.readFile(keyPath, function (readErr, keyData) {
if (readErr) {
return valCb(readErr);
}
var keyType = (keyPath.slice(-4) === '.pub'
? 'ssh' : 'pem');
try {
var key = sshpk.parseKey(keyData, keyType);
} catch (keyErr) {
return valCb(keyErr);
} }
fs.readFile(keyPath, function (readErr, keyData) {
if (readErr) {
return valCb(readErr);
}
var keyType = (keyPath.slice(-4) === '.pub'
? 'ssh' : 'pem');
try {
var key = sshpk.parseKey(keyData, keyType);
} catch (keyErr) {
return valCb(keyErr);
}
var newVal = key.fingerprint('md5').toString(); var newVal = key.fingerprint('md5').toString();
console.log('Fingerprint: %s', newVal); console.log('Fingerprint: %s', newVal);
valCb(null, newVal); valCb(null, newVal);
});
}); });
}); });
} }

View File

@ -9,7 +9,6 @@ var format = require('util').format;
var fs = require('fs'); var fs = require('fs');
var strsplit = require('strsplit'); var strsplit = require('strsplit');
var sshpk = require('sshpk'); var sshpk = require('sshpk');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('../common'); var common = require('../common');

View File

@ -14,9 +14,9 @@ var assert = require('assert-plus');
var format = require('util').format; var format = require('util').format;
var fs = require('fs'); var fs = require('fs');
var strsplit = require('strsplit'); var strsplit = require('strsplit');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('./common');
var errors = require('./errors'); var errors = require('./errors');
@ -184,38 +184,37 @@ function _addMetadataFromJsonStr(ilk, metadata, s, from, cb) {
function _addMetadataFromFile(ilk, metadata, file, cb) { function _addMetadataFromFile(ilk, metadata, file, cb) {
assert.string(ilk, 'ilk'); assert.string(ilk, 'ilk');
tilde(file, function (metaPath) { var metaPath = common.tildeSync(file);
fs.stat(metaPath, function (statErr, stats) { fs.stat(metaPath, function (statErr, stats) {
if (statErr || !stats.isFile()) { if (statErr || !stats.isFile()) {
cb(new errors.TritonError(format( cb(new errors.TritonError(format(
'"%s" is not an existing file', file))); '"%s" is not an existing file', file)));
return;
}
fs.readFile(metaPath, 'utf8', function (readErr, data) {
if (readErr) {
cb(readErr);
return; return;
} }
fs.readFile(metaPath, 'utf8', function (readErr, data) { /*
if (readErr) { * The file is either a JSON object (first non-space
cb(readErr); * char is '{'), or newline-separated key=value
return; * pairs.
} */
/* var dataTrim = data.trim();
* The file is either a JSON object (first non-space if (dataTrim.length && dataTrim[0] === '{') {
* char is '{'), or newline-separated key=value _addMetadataFromJsonStr(ilk, metadata, dataTrim, file, cb);
* pairs. } else {
*/ var lines = dataTrim.split(/\r?\n/g).filter(
var dataTrim = data.trim(); function (line) { return line.trim(); });
if (dataTrim.length && dataTrim[0] === '{') { vasync.forEachPipeline({
_addMetadataFromJsonStr(ilk, metadata, dataTrim, file, cb); inputs: lines,
} else { func: function oneLine(line, next) {
var lines = dataTrim.split(/\r?\n/g).filter( _addMetadataFromKvStr(
function (line) { return line.trim(); }); ilk, metadata, line, file, next);
vasync.forEachPipeline({ }
inputs: lines, }, cb);
func: function oneLine(line, next) { }
_addMetadataFromKvStr(
ilk, metadata, line, file, next);
}
}, cb);
}
});
}); });
}); });
} }
@ -266,20 +265,19 @@ function _addMetadataFromKfStr(ilk, metadata, s, from, cb) {
function _addMetadatumFromFile(ilk, metadata, key, file, from, cb) { function _addMetadatumFromFile(ilk, metadata, key, file, from, cb) {
assert.string(ilk, 'ilk'); assert.string(ilk, 'ilk');
tilde(file, function (filePath) { var filePath = common.tildeSync(file);
fs.stat(filePath, function (statErr, stats) { fs.stat(filePath, function (statErr, stats) {
if (statErr || !stats.isFile()) { if (statErr || !stats.isFile()) {
cb(new errors.TritonError(format( cb(new errors.TritonError(format(
'%s path "%s" is not an existing file', ilk, file))); '%s path "%s" is not an existing file', ilk, file)));
return;
}
fs.readFile(filePath, 'utf8', function (readErr, content) {
if (readErr) {
cb(readErr);
return; return;
} }
fs.readFile(filePath, 'utf8', function (readErr, content) { _addMetadatum(ilk, metadata, key, content, from, cb);
if (readErr) {
cb(readErr);
return;
}
_addMetadatum(ilk, metadata, key, content, from, cb);
});
}); });
}); });
} }

View File

@ -17,7 +17,6 @@ var mkdirp = require('mkdirp');
var path = require('path'); var path = require('path');
var rimraf = require('rimraf'); var rimraf = require('rimraf');
var sshpk = require('sshpk'); var sshpk = require('sshpk');
var tilde = require('tilde-expansion');
var vasync = require('vasync'); var vasync = require('vasync');
var common = require('./common'); var common = require('./common');
@ -785,14 +784,13 @@ function executeRbacUpdatePlan(ctx, cb) {
c.user); c.user);
vasync.pipeline({arg: {}, funcs: [ vasync.pipeline({arg: {}, funcs: [
function vars(ctx2, next2) { function vars(ctx2, next2) {
tilde('~', function (s) { ctx2.homeDir = common.tildeSync('~');
ctx2.homeDir = s; ctx2.keyName = format('%s user %s',
ctx2.keyName = format('%s user %s', c.currProfile.name, c.user);
c.currProfile.name, c.user); ctx2.keyPath = path.resolve(ctx2.homeDir, '.ssh',
ctx2.keyPath = format('%s/.ssh/%s-user-%s.id_rsa', format('%s-user-%s.id_rsa',
ctx2.homeDir, c.currProfile.name, c.user); c.currProfile.name, c.user));
next2(); next2();
});
}, },
function rmOldPrivKey(ctx2, next2) { function rmOldPrivKey(ctx2, next2) {
rimraf(ctx2.keyPath, next2); rimraf(ctx2.keyPath, next2);

View File

@ -22,7 +22,6 @@
"smartdc-auth": "2.2.3", "smartdc-auth": "2.2.3",
"strsplit": "1.0.0", "strsplit": "1.0.0",
"tabula": "1.7.0", "tabula": "1.7.0",
"tilde-expansion": "0.0.0",
"vasync": "1.6.3", "vasync": "1.6.3",
"verror": "1.6.0", "verror": "1.6.0",
"wordwrap": "1.0.0" "wordwrap": "1.0.0"