From 5e71d1bf14440d31882c101b4d8facbd61f7be6b Mon Sep 17 00:00:00 2001 From: Patrick Stadler Date: Thu, 27 Feb 2014 16:45:22 +0100 Subject: [PATCH] provide some basic information during flights with the target property --- README.md | 29 ++++++++++++++++++++++++++--- lib/flightplan.js | 19 +++++++++++++------ lib/transport/shell.js | 4 ++-- lib/transport/ssh.js | 12 ++++++------ lib/transport/transport.js | 30 ++++++++++++++++++++++++++++-- package.json | 2 +- 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9e8ef5b..e92390b 100644 --- a/README.md +++ b/README.md @@ -114,11 +114,11 @@ two types of flights: #### Local flights -Commands in local flights are executed on the **local host**. +Commands in local flights are executed on the **localhost**. ```javascript plan.local(function(transport) { - transport.hostname(); // prints the hostname of the local host + transport.hostname(); // prints the hostname of localhost }); ``` @@ -197,7 +197,7 @@ fly production --username=admin ### flightplan.local(fn) → this Calling this method registers a local flight. Local flights are -executed on your local host. When `fn` gets called a `Transport` object +executed on your localhost. When `fn` gets called a `Transport` object is passed with the first argument. ```javascript @@ -271,6 +271,21 @@ We call the Transport object `transport` in the following section to avoid confusion. However, do yourself a favor and use `local` for local, and `remote` for remote flights. +#### Accessing flight-specific information + +Flightplan provides information during flights with the `target` properties: + +```javascript +plan.remote(function(transport) { // applies to local flights as well + // Flightplan specific information + console.log(plan.target.destination); // 'production' + console.log(plan.target.hosts); // [{ host: 'www1.pstadler.sh', port: 22 }, ...] + + // Flight specific information + console.log(transport.target); // { host: 'www1.pstadler.sh', port: 22 } +}); +``` + ### transport.exec(command[, options]) → code: int, stdout: String, stderr: String To execute a command you have the choice between using `exec()` or one @@ -399,6 +414,14 @@ if(input.indexOf('yes') === -1) { // prompt for password (with UNIX-style hidden input) var password = transport.prompt('Enter your password:', { hidden: true }); + +// prompt when deploying to a specific destination +if(plan.target.destination === 'production') { + var input = transport.prompt('Ready for deploying to production? [yes]'); + if(input.indexOf('yes') === -1) { + transport.abort('user canceled flight'); + } +} ``` ### transport.log(message) diff --git a/lib/flightplan.js b/lib/flightplan.js index fab126c..d1b49fc 100644 --- a/lib/flightplan.js +++ b/lib/flightplan.js @@ -19,11 +19,11 @@ var Fiber = require('fibers') * * #### Local flights * - * Commands in local flights are executed on the **local host**. + * Commands in local flights are executed on the **localhost**. * * ```javascript * plan.local(function(transport) { - * transport.hostname(); // prints the hostname of the local host + * transport.hostname(); // prints the hostname of localhost * }); * ``` * @@ -62,6 +62,10 @@ var Fiber = require('fibers') function Flightplan() { this._briefing = null; this.flights = []; + this.target = { + destination: null, + hosts: [] + }; this.status = { aborted: false, executionTime: 0 @@ -148,7 +152,7 @@ Flightplan.prototype = { /** * Calling this method registers a local flight. Local flights are - * executed on your local host. When `fn` gets called a `Transport` object + * executed on your localhost. When `fn` gets called a `Transport` object * is passed with the first argument. * * ```javascript @@ -249,23 +253,26 @@ Flightplan.prototype = { }, start: function(destination, options) { + this.target.destination = destination; + if(this.briefing()) { this.briefing().applyOptions(options); } else { this.briefing(options); } this.logger.debug('Briefing done'); - if(this.requiresDestination() && !this.briefing().hasDestination(destination)) { + if(this.requiresDestination() && !this.briefing().hasDestination(this.target.destination)) { this.logger.error((destination || '').warn, 'is not a valid destination'); process.exit(1); } + this.target.hosts = this.briefing().getHostsForDestination(this.target.destination); if(this.isAborted()) { this.logger.error('Flightplan aborted'.error); process.exit(1); } this.logger.info('Executing flightplan with'.info, String(this.flights.length).magenta - , 'planned flight(s) to'.info, (destination || 'localhost').warn); + , 'planned flight(s) to'.info, (this.target.destination || 'localhost').warn); this.logger.space(); Fiber(function() { @@ -278,7 +285,7 @@ Flightplan.prototype = { this.logger.info('Flight'.info, this.logger.format('%s/%s', i+1, len).magenta, 'launched...'.info); this.logger.space(); - flight.start(destination); + flight.start(this.target.destination); var status = flight.getStatus() , flightNumber = this.logger.format('%s/%s', i+1, len).magenta diff --git a/lib/transport/shell.js b/lib/transport/shell.js index 2024b17..cc152f6 100644 --- a/lib/transport/shell.js +++ b/lib/transport/shell.js @@ -6,8 +6,8 @@ var util = require('util') function ShellTransport(flight) { ShellTransport.super_.call(this, flight); - this.host = 'local'; - this.logger = this.logger.cloneWithPrefix(this.host); + this.target.host = 'localhost'; + this.logger = this.logger.cloneWithPrefix(this.target.host); } util.inherits(ShellTransport, Transport); diff --git a/lib/transport/ssh.js b/lib/transport/ssh.js index a300896..522760c 100644 --- a/lib/transport/ssh.js +++ b/lib/transport/ssh.js @@ -3,11 +3,11 @@ var util = require('util') , Connection = require('ssh2') , Transport = require('./transport'); -function SSHTransport(flight, config) { +function SSHTransport(flight, target) { SSHTransport.super_.call(this, flight); - this.config = config; - this.host = this.config.host; - this.logger = this.logger.cloneWithPrefix(this.host); + this.target = target; + this.logger = this.logger.cloneWithPrefix(this.target.host); + this.connection = new Connection(); var _fiber = Fiber.current; @@ -20,7 +20,7 @@ function SSHTransport(flight, config) { // TODO }); - this.connection.connect(this.config); + this.connection.connect(this.target); return Fiber.yield(); } @@ -69,7 +69,7 @@ SSHTransport.prototype.__exec = function(cmd, args, options) { } else { this.logger.error(this.logger.format('failed').error, 'with exit code:', ret.code); fiber.throwInto(new Error(this.logger.format('`%s` failed on %s' - , cmd.white, this.config.host.warn))); + , cmd.white, this.target.host.warn))); } fiber.run(ret); }.bind(this)); diff --git a/lib/transport/transport.js b/lib/transport/transport.js index 32c353a..e5c2d3f 100644 --- a/lib/transport/transport.js +++ b/lib/transport/transport.js @@ -24,16 +24,34 @@ var util = require('util') * confusion. However, do yourself a favor and use `local` for local, and * `remote` for remote flights. * + * #### Accessing flight-specific information + * + * Flightplan provides information during flights with the `target` properties: + * + * ```javascript + * plan.remote(function(transport) { // applies to local flights as well + * // Flightplan specific information + * console.log(plan.target.destination); // 'production' + * console.log(plan.target.hosts); // [{ host: 'www1.pstadler.sh', port: 22 }, ...] + * + * // Flight specific information + * console.log(transport.target); // { host: 'www1.pstadler.sh', port: 22 } + * }); + * ``` + * * @class Transport * @return transport */ function Transport(flight) { + this.flight = flight; + this.target = {}; + this.logger = flight.logger; + this.options = { silent: false, failsafe: false }; - this.flight = flight; - this.logger = flight.logger; + commands.forEach(function(cmd) { this[cmd] = function(args, opts) { @@ -197,6 +215,14 @@ Transport.prototype = { * * // prompt for password (with UNIX-style hidden input) * var password = transport.prompt('Enter your password:', { hidden: true }); + * + * // prompt when deploying to a specific destination + * if(plan.target.destination === 'production') { + * var input = transport.prompt('Ready for deploying to production? [yes]'); + * if(input.indexOf('yes') === -1) { + * transport.abort('user canceled flight'); + * } + * } * ``` * * @method prompt(message[, options]) diff --git a/package.json b/package.json index 7d14f4e..a0da877 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "flightplan", "description": "Library for streamlining application deployment or systems administration tasks", - "version": "0.1.7", + "version": "0.1.8", "author": "Patrick Stadler ", "keywords": [ "deploy",