Comparing version 1.5.0 to 4.0.0
@@ -1,35 +0,35 @@ | ||
// Expose modules. | ||
exports.parse = parse; | ||
exports.format = format; | ||
'use strict'; | ||
/** | ||
* Parse a remote string. | ||
* | ||
* @param {string} str | ||
* @returns {object} | ||
*/ | ||
exports.__esModule = true; | ||
exports.parseRemote = parseRemote; | ||
exports.formatRemote = formatRemote; | ||
function parse(str) { | ||
if (!str) | ||
throw new Error('Host cannot be empty.'); | ||
var _util = require('./util'); | ||
var matches = str.match(/(.*)@([^:]*):?(.*)/); | ||
function parseRemote(remote) { | ||
if (remote && remote.host) return remote; | ||
if (typeof remote !== 'string') throw new Error('A remote must be a string'); | ||
if (remote === '') throw new Error('A remote cannot be an empty string'); | ||
if (!matches) | ||
return {user: 'deploy', host: str}; | ||
const matches = remote.match(/(([^@:]+)@)?([^@:]+)(:(.+))?/); | ||
return {user: matches[1], host: matches[2], port: +matches[3] || undefined}; | ||
} | ||
if (matches) { | ||
const user = matches[2], | ||
host = matches[3], | ||
port = matches[5]; | ||
/** | ||
* Format a remote object. | ||
* | ||
* @param {object} obj Remote object | ||
* @returns {string} | ||
*/ | ||
const options = { user, host }; | ||
if (port) options.port = Number(port); | ||
if (!user) { | ||
(0, _util.deprecateV3)('Default user "deploy" is deprecated, please specify it explictly.'); | ||
options.user = 'deploy'; | ||
} | ||
return options; | ||
} | ||
function format(obj) { | ||
var str = obj.user + '@' + obj.host; | ||
return { user: 'deploy', host: remote }; | ||
} | ||
return str; | ||
} | ||
function formatRemote({ user, host }) { | ||
return `${user}@${host}`; | ||
} |
@@ -1,17 +0,67 @@ | ||
var util = { | ||
'use strict'; | ||
/** | ||
* Resolves a windows path into a valid msysgit path, where applicable | ||
* @param {string} path | ||
* @returns {string} | ||
*/ | ||
resolveMsysGitPath: function (path) { | ||
var matches; | ||
if ((matches = /^(\w):\\(.*)$/.exec(path)) !== null) { | ||
return '/' + matches[1] + '/' + matches[2].replace(/\\/g, '/'); | ||
} else | ||
return path; | ||
} | ||
}; | ||
exports.__esModule = true; | ||
exports.exec = exports.series = undefined; | ||
module.exports = util; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
exports.deprecateV3 = deprecateV3; | ||
var _child_process = require('child_process'); | ||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } | ||
/* eslint-disable no-console */ | ||
const series = exports.series = (() => { | ||
var _ref = _asyncToGenerator(function* (tasks) { | ||
return new Promise(function (resolve, reject) { | ||
const tasksCopy = [...tasks]; | ||
const next = function next(results) { | ||
if (tasksCopy.length === 0) { | ||
resolve(results); | ||
return; | ||
} | ||
const task = tasksCopy.shift(); | ||
task().then(function (result) { | ||
return next([...results, result]); | ||
}).catch(reject); | ||
}; | ||
next([]); | ||
}); | ||
}); | ||
return function series(_x) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
})(); | ||
const DEFAULT_CMD_OPTIONS = { maxBuffer: 1000 * 1024 }; | ||
const exec = exports.exec = (() => { | ||
var _ref2 = _asyncToGenerator(function* (cmd, options, childModifier) { | ||
return new Promise(function (resolve, reject) { | ||
const child = (0, _child_process.exec)(cmd, _extends({}, DEFAULT_CMD_OPTIONS, options), function (error, stdout, stderr) { | ||
if (error) { | ||
/* eslint-disable no-param-reassign */ | ||
error.stdout = stdout; | ||
error.stderr = stderr; | ||
error.child = child; | ||
/* eslint-enable no-param-reassign */ | ||
reject(error); | ||
} else { | ||
resolve({ child, stdout, stderr }); | ||
} | ||
}); | ||
if (childModifier) childModifier(child); | ||
}); | ||
}); | ||
return function exec(_x2, _x3, _x4) { | ||
return _ref2.apply(this, arguments); | ||
}; | ||
})(); | ||
function deprecateV3(...args) { | ||
console.warn(...args, 'It will break in v3.0.0.'); | ||
} |
{ | ||
"name": "ssh-pool", | ||
"version": "1.5.0", | ||
"version": "4.0.0", | ||
"description": "Run remote commands over a pool of server using SSH.", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/shipitjs/ssh-pool.git" | ||
}, | ||
"main": "lib/index.js", | ||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-traverse", | ||
"author": "Bergé Greg <berge.greg@gmail.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/shipitjs/ssh-pool/issues" | ||
}, | ||
"homepage": "https://github.com/shipitjs/ssh-pool", | ||
"devDependencies": { | ||
"chai": "^2.1.2", | ||
"mocha": "^2.2.1", | ||
"rewire": "^2.3.1", | ||
"sinon": "^1.14.1", | ||
"sinon-chai": "^2.7.0", | ||
"std-mocks": "^1.0.0" | ||
}, | ||
"homepage": "https://github.com/shipitjs/shipit", | ||
"dependencies": { | ||
"bluebird": "^2.9.14", | ||
"lodash": "^3.5.0", | ||
"sprintf-js": "^1.0.2", | ||
"stream-line-wrapper": "^0.1.1", | ||
"tmp": "^0.0.33", | ||
"whereis": "^0.4.0" | ||
} | ||
} |
211
README.md
# ssh-pool | ||
[![Build Status](https://travis-ci.org/shipitjs/ssh-pool.svg?branch=master)](https://travis-ci.org/shipitjs/ssh-pool) | ||
[![Dependency Status](https://david-dm.org/shipitjs/ssh-pool.svg?theme=shields.io)](https://david-dm.org/shipitjs/ssh-pool) | ||
[![devDependency Status](https://david-dm.org/shipitjs/ssh-pool/dev-status.svg?theme=shields.io)](https://david-dm.org/shipitjs/ssh-pool#info=devDependencies) | ||
[![Build Status][build-badge]][build] | ||
[![version][version-badge]][package] | ||
[![MIT License][license-badge]][license] | ||
Run remote commands over a pool of server using SSH. | ||
## Install | ||
``` | ||
```sh | ||
npm install ssh-pool | ||
@@ -17,11 +16,11 @@ ``` | ||
```js | ||
var sshPool = require('ssh-pool'); | ||
import { ConnectionPool } from 'ssh-pool' | ||
var pool = new sshPool.ConnectionPool(['user@server1', 'user@server2']); | ||
const pool = new ConnectionPool(['user@server1', 'user@server2']) | ||
pool.run('hostname') | ||
.then(function (results) { | ||
console.log(results[0].stdout); // 'server1' | ||
console.log(results[1].stdout); // 'server2' | ||
}); | ||
async function run() { | ||
const results = await pool.run('hostname') | ||
console.log(results[0].stdout) // 'server1' | ||
console.log(results[1].stdout) // 'server2' | ||
} | ||
``` | ||
@@ -33,3 +32,3 @@ | ||
**Arguments:** | ||
**Parameters:** | ||
@@ -43,2 +42,3 @@ ``` | ||
@param {function} [options.log] Log method | ||
@param {boolean} [options.asUser] Use a custom user to run command | ||
``` | ||
@@ -49,13 +49,16 @@ | ||
```js | ||
// Default user will be deploy and ssh default port. | ||
new Connection({remote: 'localhost'}); | ||
// You specify user and host | ||
new Connection({ remote: 'user@localhost' }) | ||
// Default ssh port will be used. | ||
new Connection({remote: 'user@localhost'}); | ||
// You can specify a custom SSH port | ||
new Connection({ remote: 'user@localhost:4000' }) | ||
// Custom user and custom port. | ||
new Connection({remote: 'user@localhost:22'}); | ||
// Object syntax. | ||
new Connection({remote: {user: 'user', host: 'localhost', port: 22}}); | ||
// You can also define remote using an object | ||
new Connection({ | ||
remote: { | ||
user: 'user', | ||
host: 'localhost', | ||
port: 4000, | ||
}, | ||
}) | ||
``` | ||
@@ -66,8 +69,10 @@ | ||
```js | ||
var connection = new Connection({ | ||
import { Connection } from 'ssh-pool' | ||
const connection = new Connection({ | ||
remote: 'localhost', | ||
log: console.log.bind(console) | ||
}); | ||
log: (...args) => console.log(...args), | ||
}) | ||
connection.run('pwd'); | ||
connection.run('pwd') | ||
@@ -79,115 +84,125 @@ // Will output: | ||
### connection.run(command, [options], [cb]) | ||
### connection.run(command, [options]) | ||
Run a command on the remote server, you can specify custom `childProcess.exec` options. A callback or a promise can be used. | ||
Run a command on the remote server, you can specify custom `childProcess.exec` options. | ||
**Arguments:** | ||
**Parameters:** | ||
``` | ||
@param {string} command Command | ||
@param {object} [options] Exec options | ||
@param {function} [cb] Callback | ||
@returns {Promise} | ||
@param {string} command Command to run | ||
@param {object} [options] Options | ||
@param {boolean} [options.tty] Force a TTY allocation. | ||
@returns {ExecResult} | ||
@throws {ExecError} | ||
``` | ||
```js | ||
connection.run('ls', {env: {NODE_ENV: 'test'}}) | ||
.then(function (result) { | ||
result.stdout; // stdout output | ||
result.stderr; // stderr output | ||
result.child; // child object | ||
}); | ||
// Run "ls" command on a remote server | ||
connection.run('ls').then(res => { | ||
console.log(res.stdout) // file1 file2 file3 | ||
}) | ||
``` | ||
### connection.copy(src, dest, [options], [cb]) | ||
### connection.copyToRemote(src, dest, [options]) | ||
Copy a file or a directory to a remote server, you can specify custom `childProcess.exec` options. A callback or a promise can be used. | ||
Copy a file or a directory from local to a remote server, you can specify custom `childProcess.exec` options. It uses rsync under the hood. | ||
**Arguments:** | ||
**Parameters:** | ||
``` | ||
@param {string} src Source | ||
@param {string} dest Destination | ||
@param {object} [options] Exec Options | ||
@param {function} [cb] Callback | ||
@returns {Promise} | ||
* @param {string} src Source | ||
* @param {string} dest Destination | ||
* @param {object} [options] Options | ||
* @param {string[]} [options.ignores] Specify a list of files to ignore. | ||
* @param {string[]|string} [options.rsync] Specify a set of rsync arguments. | ||
* @returns {ExecResult} | ||
* @throws {ExecError} | ||
``` | ||
```js | ||
connection.copy('./localfile', '/remote-file', {env: {NODE_ENV: 'test'}}) | ||
.then(function (result) { | ||
result.stdout; // stdout output | ||
result.stderr; // stderr output | ||
result.child; // child object | ||
}); | ||
// Copy a local file to a remote file using Rsync | ||
connection.copyToRemote('./localfile', '/remote-file').then(() => { | ||
console.log('File copied!') | ||
}) | ||
``` | ||
### connection.copyFromRemote(src, dest, [options]) | ||
Copy a file or a directory from a remote server to local, you can specify custom `childProcess.exec` options. It uses rsync under the hood. | ||
**Parameters:** | ||
``` | ||
* @param {string} src Source | ||
* @param {string} dest Destination | ||
* @param {object} [options] Options | ||
* @param {string[]} [options.ignores] Specify a list of files to ignore. | ||
* @param {string[]|string} [options.rsync] Specify a set of rsync arguments. | ||
* @returns {ExecResult} | ||
* @throws {ExecError} | ||
``` | ||
```js | ||
// Copy a remote file to a local file using Rsync | ||
connection.copyFromRemote('/remote-file', './local-file').then(() => { | ||
console.log('File copied!') | ||
}) | ||
``` | ||
### new ConnectionPool(connections, [options]) | ||
Create a new pool of connections and custom options for all connections. | ||
You can use either short syntax or connections to create a pool. | ||
If you use the short syntax, connections will be automatically created, else you can use previous created connections. | ||
```js | ||
import { Connection, ConnectionPool } from 'ssh-pool' | ||
```js | ||
// Use shorthand. | ||
var pool = new ConnectionPool(['server1', 'server2']); | ||
const pool = new ConnectionPool(['server1', 'server2']) | ||
// Use previously created connections. | ||
var connection1 = new Connection({remote: 'server1'}); | ||
var connection2 = new Connection({remote: 'server2'}); | ||
var pool = new ConnectionPool([connection1, connection2]); | ||
const connection1 = new Connection({ remote: 'server1' }) | ||
const connection2 = new Connection({ remote: 'server2' }) | ||
const pool = new ConnectionPool([connection1, connection2]) | ||
``` | ||
### pool.run(command, [options], [cb]) | ||
Connection Pool accepts exactly the same methods as Connection. It runs commands in parallel on each server defined in the pool. You get an array of results. | ||
Same as `connection.run`, except that the command is executed in parallel on each server of the pool. | ||
### isRsyncSupported() | ||
**Arguments:** | ||
Test if rsync is supported on the local machine. | ||
``` | ||
@param {string} command Command | ||
@param {object} [options] Options | ||
@param {function} [cb] Callback | ||
@returns {Promise} | ||
``` | ||
```js | ||
pool.run('hostname') | ||
.then(function (results) { | ||
// ... | ||
}); | ||
``` | ||
import { isRsyncSupported } from 'ssh-pool' | ||
### pool.copy(src, dest, [options], [cb]) | ||
Same as `connection.copy`, except that the copy is done in parallel on each server of the pool. | ||
**Options:** | ||
isRsyncSupported().then(supported => { | ||
if (supported) { | ||
console.log('Rsync is supported!') | ||
} else { | ||
console.log('Rsync is not supported!') | ||
} | ||
}) | ||
``` | ||
@param {object} [options.direction] Direction of copy | ||
``` | ||
Also all exec options are supported. | ||
### exec(cmd, options, childModifier) | ||
**Arguments:** | ||
Execute a command and return an object containing `{ child, stdout, stderr }`. | ||
``` | ||
@param {string} src Source | ||
@param {string} dest Destination | ||
@param {object} options Options | ||
@param {function} [cb] Callback | ||
@returns {Promise} | ||
``` | ||
```js | ||
import { exec } from 'ssh-pool' | ||
```js | ||
pool.copy('./localfile', '/remote-file') | ||
.then(function (results) { | ||
// ... | ||
}); | ||
exec('echo "hello"') | ||
.then(({ stdout }) => console.log(stdout)) | ||
.catch(({ stderr, stdout }) => console.error(stderr)) | ||
``` | ||
## License | ||
MIT | ||
[build-badge]: https://img.shields.io/travis/shipitjs/shipit.svg?style=flat-square | ||
[build]: https://travis-ci.org/shipitjs/shipit | ||
[version-badge]: https://img.shields.io/npm/v/ssh-pool.svg?style=flat-square | ||
[package]: https://www.npmjs.com/package/ssh-pool | ||
[license-badge]: https://img.shields.io/npm/l/ssh-pool.svg?style=flat-square | ||
[license]: https://github.com/shipitjs/shipit/blob/master/LICENSE |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
3
0
203
36755
726
1
2
+ Addedtmp@^0.0.33
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedtmp@0.0.33(transitive)
- Removedbluebird@^2.9.14
- Removedlodash@^3.5.0
- Removedsprintf-js@^1.0.2
- Removedbluebird@2.11.0(transitive)
- Removedlodash@3.10.1(transitive)
- Removedsprintf-js@1.1.3(transitive)