Permalink
Browse files

reworked web interface to use new internal api

  • Loading branch information...
1 parent 0eac73c commit ba64f03f8b1273cc610a947572892aef5095d7e5 Russell Haering committed Mar 19, 2012
View
74 lib/dreadnot.js
@@ -150,22 +150,82 @@ Dreadnot.prototype.getSummary = function(callback) {
};
-Dreadnot.prototype.getStacks = function(callback) {
+Dreadnot.prototype.getStackSummaries = function(callback) {
var self = this,
stackNames = Object.keys(this.config.stacks);
- callback(null, stackNames.map(function(stackName) {
- return self._getStack(stackName);
- }));
+ async.map(stackNames, function(stackName, callback) {
+ self._getStack(stackName).getSummary(callback);
+ }, callback);
+};
+
+
+Dreadnot.prototype.getStackSummary = function(stackName, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.getSummary(callback);
+ }
+};
+
+
+Dreadnot.prototype.getRegionSummaries = function(stackName, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.getRegionSummaries(callback);
+ }
+};
+
+
+Dreadnot.prototype.getRegionSummary = function(stackName, regionName, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.getRegionSummary(regionName, callback);
+ }
+};
+
+
+Dreadnot.prototype.deploy = function(stackName, regionName, to, user, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.run('deploy', regionName, to, user, callback);
+ }
+};
+
+
+Dreadnot.prototype.getDeploymentSummaries = function(stackName, regionName, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.getDeploymentSummaries(regionName, callback);
+ }
+};
+
+
+Dreadnot.prototype.getDeploymentSummary = function(stackName, regionName, deploymentName, callback) {
+ var stack = this._stacks[stackName];
+ if (!stack) {
+ callback(new errors.NotFoundError('Stack not found'));
+ } else {
+ stack.getDeploymentSummary(regionName, deploymentName, callback);
+ }
};
-Dreadnot.prototype.getStack = function(name, callback) {
- var stack = this._stacks[name];
+Dreadnot.prototype.getDeploymentLog = function(stackName, regionName, deploymentName, options, callback) {
+ var stack = this._stacks[stackName];
if (!stack) {
callback(new errors.NotFoundError('Stack not found'));
} else {
- callback(null, stack);
+ stack.getDeploymentLog(regionName, deploymentName, options, callback);
}
};
View
54 lib/stack.js
@@ -353,7 +353,8 @@ Stack.prototype.getSummary = function(callback) {
if (this.module.get_latestRevision) {
getter = this.module.get_latestRevision.bind(this, {environment: this.config.env});
} else {
- getter = git.getLatestRevision.bind(git, this.getRepoUrl(), this.stackConfig.tip);
+ getter = function(callback) { callback(null, '90c32c8f2d840d20c0862c03dbe9ea6843c56235'); };
+ //getter = git.getLatestRevision.bind(git, this.getRepoUrl(), this.stackConfig.tip);
}
this._getCached('latest_revision', this.stackConfig.tip_ttl, getter, function(err, rev) {
@@ -502,31 +503,60 @@ Stack.prototype.getDeploymentSummaries = function(region, callback) {
};
-Stack.prototype.getDeploymentLog = function(region, number, callback) {
+Stack.prototype.getDeploymentLog = function(region, number, options, callback) {
var self = this,
depPath = ['stacks', self.name, 'regions', region, 'deployments', number].join('.'),
logPath = [depPath, 'log'].join('.'),
- endPath = [depPath, 'end'].join('.');
+ endPath = [depPath, 'end'].join('.'),
+ fromIdx, stream;
+
+ if (!callback) {
+ callback = options;
+ options = {};
+ }
+
+ fromIdx = options.fromIdx || 0;
+ stream = options.stream !== undefined ? options.stream : true;
self._getDeploymentSummary(region, number, function(err, summary) {
- var depLog = new events.EventEmitter();
+ var depLog = new events.EventEmitter(),
+ idx = 0,
+ block = true;
+
callback(err, depLog);
function emitEntry(entry) {
- depLog.emit('data', entry);
+ if (idx++ >= fromIdx) {
+ depLog.emit('data', entry);
+ block = false;
+ }
}
if (!err) {
+ // Emit all immediately available log entries
summary.log.forEach(emitEntry);
- if (!summary.finished) {
- self.dreadnot.emitter.on(logPath, emitEntry);
- self.dreadnot.emitter.once(endPath, function(success) {
- self.dreadnot.emitter.removeListener(logPath, emitEntry);
- depLog.emit('end', success);
- });
+ if (stream) {
+ if (!summary.finished) {
+ self.dreadnot.emitter.on(logPath, emitEntry);
+ self.dreadnot.emitter.once(endPath, function(success) {
+ self.dreadnot.emitter.removeListener(logPath, emitEntry);
+ depLog.emit('end', success);
+ });
+ } else {
+ depLog.emit('end', summary.success);
+ }
} else {
- depLog.emit('end', summary.success);
+ if (summary.finished) {
+ depLog.emit('end', summary.success);
+ } else if (block) {
+ self.dreadnot.emitter.once(logPath, function(entry) {
+ emitEntry(entry);
+ depLog.emit('segment');
+ });
+ } else {
+ depLog.emit('segment');
+ }
}
}
});
View
72 lib/web/app.js
@@ -19,7 +19,6 @@ var path = require('path');
var connect = require('connect');
var express = require('express');
-var socketio = require('socket.io');
var log = require('logmagic').local('web.app');
var misc = require('util/misc');
@@ -68,53 +67,12 @@ function buildAuthMiddleware(config, read) {
};
}
-// Register socket.io routing
-function authorizeStream(dreadnot, sessionStore) {
- return function(data, callback) {
- var cookie;
-
- if (dreadnot.config.login_required === false || dreadnot.config.unauthorized_read) {
- log.info('stream authorized by default');
- callback(null, true);
- return;
- }
-
- log.info('attempting to authorize stream', {
- cookie: data.headers.cookie
- });
-
- if (!data.headers.cookie) {
- callback(null, false);
- return;
- }
-
- cookie = connect.utils.parseCookie(data.headers.cookie);
-
- if (!cookie['connect.sid']) {
- callback(null, false);
- return;
- }
-
- sessionStore.get(cookie['connect.sid'], function(err, session) {
- log.info('attempted to retrieve session', {
- sid: cookie['connect.sid'],
- err: err,
- session: session
- });
-
- if (err || !session || !session.authed) {
- callback(null, false);
- } else {
- callback(null, true);
- }
- });
- };
-}
-
exports.registerWeb = function(dreadnot, authdb) {
var app = express.createServer(),
- webHandlers = handlers.web.getWebHandlers(dreadnot, authdb);
+ webHandlers = handlers.web.getWebHandlers(dreadnot, authdb),
+ readAuth = buildAuthMiddleware(dreadnot.config, true),
+ writeAuth = buildAuthMiddleware(dreadnot.config, false);
app.configure(function() {
// Settings
@@ -124,7 +82,19 @@ exports.registerWeb = function(dreadnot, authdb) {
app.use(middleware.apiresponse());
});
- app.get('/', webHandlers.getApplication);
+ // Public URLs
+ app.get('/login', webHandlers.getLogin);
+ app.post('/login', webHandlers.attemptLogin);
+
+ // Private URLs
+ app.get('/', readAuth, webHandlers.getStacks);
+ app.get('/logout', readAuth, webHandlers.logout);
+ app.get('/stacks/:stack/regions/:region', readAuth, webHandlers.getDeployments);
+ app.post('/stacks/:stack/regions/:region', writeAuth, webHandlers.deploy);
+ app.get('/stacks/:stack/regions/:region/deployments/:deployment', readAuth, webHandlers.getDeployment);
+ app.get('/stacks/:stack/regions/:region/deployments/:deployment/log', readAuth, webHandlers.getDeploymentLog);
+ app.get('/warning', writeAuth, webHandlers.getWarning);
+ app.post('/warning', writeAuth, webHandlers.saveWarning);
return app;
};
@@ -138,6 +108,7 @@ exports.registerAPI = function(dreadnot, authdb) {
// API is behind Basic auth
basic = express.basicAuth(function(username, password, callback) {
authdb.validate(username, password, function(err, valid) {
+ return callback(err, null);
if (err || !valid) {
callback(err, null);
} else {
@@ -170,17 +141,9 @@ exports.registerAPI = function(dreadnot, authdb) {
};
-exports.registerSocketIO = function(app, dreadnot, sessionStore) {
- var io = socketio.listen(app, {logger: log, authorization: authorizeStream(dreadnot, sessionStore)}),
- streamingHandlers = handlers.streaming.getStreamingHandlers(dreadnot);
- io.sockets.on('connection', streamingHandlers.handleConnection);
-};
-
-
exports.run = function(port, dreadnot) {
var app = express.createServer(),
authdb = auth.loadDBFromFile(dreadnot.config.htpasswd_file),
- streamHandlers = handlers.streaming.getStreamingHandlers(dreadnot),
sessionStore = new connect.session.MemoryStore({maxAge: 7 * 24 * 60 * 60 * 1000});
app.configure(function() {
@@ -196,7 +159,6 @@ exports.run = function(port, dreadnot) {
app.use('/static', express.static(STATIC_DIR));
app.use('/api', exports.registerAPI(dreadnot, authdb));
app.use('/', exports.registerWeb(dreadnot, authdb));
- exports.registerSocketIO(app, dreadnot, sessionStore);
// Catch 404s
app.get('*', function(req, res, next) {
View
98 lib/web/handlers/api.js
@@ -28,105 +28,47 @@ exports.getAPIHandlers = function(dreadnot, authdb) {
}
function getStacks(req, res) {
- dreadnot.getStacks(function(err, stacks) {
- if (err) {
- res.respond(err);
- } else {
- async.map(stacks, function(stack, callback) {
- stack.getSummary(callback);
- }, res.respond);
- }
- });
+ dreadnot.getStackSummaries(res.respond);
}
function getStack(req, res) {
- dreadnot.getStack(req.params.stack, function(err, stack) {
- if (err) {
- res.respond(err);
- } else {
- stack.getSummary(res.respond);
- }
- });
+ dreadnot.getStackSummary(req.params.stack, res.respond);
}
function getRegions(req, res) {
- async.waterfall([
- function(callback) {
- dreadnot.getStack(req.params.stack, callback);
- },
-
- function(stack, callback) {
- stack.getRegionSummaries(callback);
- }
- ], res.respond);
+ dreadnot.getRegionSummaries(req.params.stack, res.respond);
}
function getRegion(req, res) {
- async.waterfall([
- function(callback) {
- dreadnot.getStack(req.params.stack, callback);
- },
-
- function(stack, callback) {
- stack.getRegionSummary(req.params.region, callback);
- }
- ], res.respond);
+ dreadnot.getRegionSummary(req.params.stack, req.params.region, res.respond);
}
- // Render a region view with a list of deployments
function getDeployments(req, res) {
- var stackName = req.params.stack,
- regionName = req.params.region;
-
- async.waterfall([
- dreadnot.getStack.bind(dreadnot, stackName),
-
- function(stack, callback) {
- stack.getDeploymentSummaries(regionName, callback);
- }
- ], res.respond);
+ dreadnot.getDeploymentSummaries(req.params.stack, req.params.region, res.respond);
}
- // Render a view of a single deployment with the log
function getDeployment(req, res) {
- var stackName = req.params.stack,
- regionName = req.params.region,
- deploymentNumber = req.params.deployment;
-
- async.waterfall([
- dreadnot.getStack.bind(dreadnot, stackName),
-
- function(stack, callback) {
- stack.getDeploymentSummary(regionName, deploymentNumber, callback);
- }
- ], res.respond);
+ dreadnot.getDeploymentSummary(req.params.stack, req.params.region, req.params.deployment, res.respond);
}
function getDeploymentLog(req, res) {
var stackName = req.params.stack,
regionName = req.params.region,
deploymentNumber = req.params.deployment;
- dreadnot.getStack(stackName, function(err, stack) {
+ dreadnot.getDeploymentLog(stackName, regionName, deploymentNumber, function(err, depLog) {
if (err) {
res.respond(err);
return;
}
- stack.getDeploymentLog(regionName, deploymentNumber, function(err, depLog) {
- if (err) {
- res.respond(err);
- return;
- }
-
- res.header('Transfer-Encoding', 'chunked');
- res.setHeader('Content-Type', 'application/json');
- depLog.on('data', function(item) {
- res.write(JSON.stringify(item) + '\n');
- });
- depLog.on('end', function(success) {
- res.end();
- });
+ res.header('Transfer-Encoding', 'chunked');
+ res.setHeader('Content-Type', 'application/json');
+ depLog.on('data', function(item) {
+ res.write(JSON.stringify(item) + '\n');
+ });
+ depLog.on('end', function(success) {
+ res.end();
});
});
}
@@ -140,16 +82,10 @@ exports.getAPIHandlers = function(dreadnot, authdb) {
to = req.body.to_revision, user;
async.waterfall([
- dreadnot.getStack.bind(dreadnot, stackName),
-
- function(stack, callback) {
- stack.run('deploy', regionName, to, req.remoteUser.name, function(err, number) {
- callback(err, stack, number);
- });
- },
+ dreadnot.deploy.bind(dreadnot, stackName, regionName, to, req.remoteUser.name),
- function(stack, number, callback) {
- stack.getDeploymentSummary(regionName, number, callback);
+ function(number, callback) {
+ dreadnot.getDeploymentSummary(stackName, regionName, number, callback);
}
], res.respond);
}
View
1 lib/web/handlers/index.js
@@ -1,5 +1,4 @@
module.exports = {
'api': require('./api'),
- 'streaming': require('./streaming'),
'web': require('./web')
};
View
52 lib/web/handlers/streaming.js
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011 Rackspace
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-var async = require('async');
-
-
-exports.getStreamingHandlers = function(dreadnot) {
- function streamLog(socket, details) {
- var depPath = ['stacks', details.stack, 'regions', details.region, 'deployments', details.deployment].join('.');
- dreadnot.getStack(details.stack, function(err, stack) {
- if (err) {
- return;
- }
-
- stack.getDeploymentLog(details.region, details.deployment, function(err, depLog) {
- if (err) {
- return;
- }
-
- depLog.on('data', function(data) {
- socket.emit([depPath, 'log'].join('.'), data);
- });
-
- depLog.on('end', function(success) {
- socket.emit([depPath, 'end'].join('.'), success);
- });
- });
- });
- }
-
- function handleConnection(socket) {
- socket.on('request log', streamLog.bind(null, socket));
- }
-
- return {
- handleConnection: handleConnection
- };
-};
View
209 lib/web/handlers/web.js
@@ -15,11 +15,214 @@
*
*/
+var async = require('async');
+
+var sprintf = require('../../util/sprintf');
+var misc = require('../../util/misc');
+var errors = require('../../errors');
+
+var viewHelpers = require('../view_helpers');
+
+var api = require('./api');
+
exports.getWebHandlers = function(dreadnot, authdb) {
- return {
- getApplication: function(req, res) {
- res.render('dn2.jade');
+ // Utility function for rendering responses
+ function render(req, res, template, data, options) {
+ res.render(template, misc.merge({
+ user: req.remoteUser,
+ title: dreadnot.config.name,
+ env: dreadnot.config.env,
+ url: req.originalUrl,
+ emsg: res.emsg,
+ wmsg: dreadnot.warning,
+ helpers: viewHelpers,
+ data: data
+ }, options || {}));
+ }
+
+ // Render an error page
+ function handleError(req, res, err) {
+ switch (err.name) {
+ case 'NotFoundError':
+ render(req, res, 'error', err, {status: 404});
+ break;
+ default:
+ render(req, res, 'error', err, {status: 500});
}
+ }
+
+ // Build a callback that renders on success or errors on failure
+ function renderCallback(req, res, template) {
+ return function(err, data) {
+ if (err) {
+ handleError(req, res, err);
+ } else {
+ console.log('DATA', data);
+ render(req, res, template, data);
+ }
+ };
+ }
+
+ // Render the Login page
+ function getLogin(req, res) {
+ var next = req.param('next');
+ render(req, res, 'login.jade', {next: next});
+ }
+
+ // Handle Login attempts, redirect on success, render Login with error on failure
+ function attemptLogin(req, res) {
+ var username = req.param('username'),
+ password = req.param('password'),
+ next = req.param('next', '/');
+
+ authdb.validate(username, password, function(err, valid) {
+ if (valid) {
+ req.session.authed = true;
+ req.session.username = username;
+ res.redirect(next);
+ } else {
+ res.emsg = 'Invalid Username or Password';
+ render(req, res, 'login.jade', {next: next});
+ }
+ });
+ }
+
+ // Handle logout attempts
+ function logout(req, res) {
+ req.session.destroy();
+ res.redirect('/');
+ }
+
+ // Render the main overview page
+ function getStacks(req, res) {
+ var data = {};
+ async.auto({
+ stacks: function(callback) {
+ dreadnot.getStackSummaries(function(err, stacks) {
+ data.stacks = stacks;
+ callback(err);
+ });
+ },
+
+ regions: ['stacks', function(callback) {
+ async.forEach(data.stacks, function(stack, callback) {
+ dreadnot.getRegionSummaries(stack.name, function(err, regions) {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ stack.regions = regions;
+ async.forEach(stack.regions, function(region, callback) {
+ dreadnot.getDeploymentSummary(stack.name, region.name, region.latest_deployment, function(err, deployment) {
+ region.latest_deployment = deployment;
+ callback(err);
+ });
+ }, callback);
+ });
+ }, callback);
+ }],
+ }, function(err) {
+ renderCallback(req, res, 'stacks.jade')(err, data);
+ });
+ }
+
+ // Render a region view with a list of deployments
+ function getDeployments(req, res) {
+ async.parallel({
+ stack: dreadnot.getStackSummary.bind(dreadnot, req.params.stack),
+ region: dreadnot.getRegionSummary.bind(dreadnot, req.params.stack, req.params.region),
+ deployments: dreadnot.getDeploymentSummaries.bind(dreadnot, req.params.stack, req.params.region)
+ }, renderCallback(req, res, 'deployments.jade'));
+ }
+
+ // Render a view of a single deployment with the log
+ function getDeployment(req, res) {
+ async.parallel({
+ stack: dreadnot.getStackSummary.bind(dreadnot, req.params.stack),
+ region: dreadnot.getRegionSummary.bind(dreadnot, req.params.stack, req.params.region),
+ deployment: dreadnot.getDeploymentSummary.bind(dreadnot, req.params.stack, req.params.region, req.params.deployment)
+ }, renderCallback(req, res, 'deployment.jade'));
+ }
+
+ function getDeploymentLog(req, res) {
+ var stackName = req.params.stack,
+ regionName = req.params.region,
+ deploymentNumber = req.params.deployment,
+ fromIdx = req.param('from', 0),
+ entries = [];
+
+ dreadnot.getDeploymentLog(stackName, regionName, deploymentNumber, {fromIdx: fromIdx, stream: false}, function(err, depLog) {
+ if (err) {
+ res.respond(err);
+ return;
+ }
+
+ res.writeHead('200', {'content-type': 'application/json'});
+
+ depLog.on('data', function(item) {
+ entries.push(item);
+ });
+
+ depLog.on('end', function(success) {
+ entries.push(success);
+ res.end(JSON.stringify(entries));
+ });
+
+ depLog.on('segment', function() {
+ res.end(JSON.stringify(entries));
+ });
+ });
+ }
+
+ // Handle attempted deployments. Redirect to the deployment on success. On
+ // stack locked errors, redirect to the region view, otherwise a full error
+ // view.
+ function deploy(req, res) {
+ var stackName = req.params.stack,
+ regionName = req.params.region,
+ to = req.body.to_revision, user;
+
+ dreadnot.deploy(stackName, regionName, to, req.remoteUser.name, function(err, number) {
+ if (err) {
+ res.respond(err);
+ return;
+ } else {
+ res.redirect(sprintf('/stacks/%s/regions/%s/deployments/%s', stackName, regionName, number));
+ }
+ });
+ }
+
+ // Render the warning editing view
+ function getWarning(req, res) {
+ render(req, res, 'warning.jade', {});
+ }
+
+ // Store the warning message
+ function saveWarning(req, res) {
+ var text = req.body.action === 'save' ? req.body.warning_text : '';
+
+ dreadnot.setWarning(text, function(err) {
+ if (err) {
+ res.emsg = err.message;
+ }
+ getWarning(req, res);
+ });
+ }
+
+ // Return bound handlers
+ return {
+ getLogin: getLogin,
+ attemptLogin: attemptLogin,
+ logout: logout,
+ getStacks: getStacks,
+ getDeployments: getDeployments,
+ getDeployment: getDeployment,
+ getDeploymentLog: getDeploymentLog,
+ deploy: deploy,
+ getWarning: getWarning,
+ saveWarning: saveWarning,
+ handleError: handleError
};
};
View
8 lib/web/views/deployment.jade
@@ -1,19 +1,19 @@
extends layout-deploy
block title
- h1 Deployment \##{data.name} of #{data.stack.name}:#{data.region.name}
+ h1 Deployment \##{data.deployment.name} of #{data.stack.name}:#{data.region.name}
block upnav
a(href='/stacks/#{data.stack.name}/regions/#{data.region.name}') ← back to #{data.region.name}
block scripts
- - var log = {stack: data.stack.name, region: data.region.name, deployment: data.name};
+ - var log = {stack: data.stack.name, region: data.region.name, deployment: data.deployment.name};
script(type='text/javascript')
$(function() { streamLogs(!{JSON.stringify(log)}); });
block content
- p #{new Date(data.time).toUTCString()} by #{data.user}
- p !{helpers.buildDiffSegment(data.stack.github_href, data.from_revision, data.to_revision)}
+ p #{new Date(data.deployment.time).toUTCString()} by #{data.deployment.user}
+ p !{helpers.buildDiffSegment(data.stack.github_href, data.deployment.from_revision, data.deployment.to_revision)}
pre.deployment_log
View
10 lib/web/views/deployments.jade
@@ -6,10 +6,10 @@ block scripts
$(function() { dreadNow() });
block title
- h1 #{data.stack.name}:#{data.name}
+ h1 #{data.stack.name}:#{data.region.name}
block upnav
- a(href='/') ← back to #{data.env.name}
+ a(href='/') ← back to #{env}
block content
- if (user.authorized)
@@ -24,10 +24,10 @@ block content
a(href='#')#fearless.btn.primary Deploy Anyway
a(href='#')#fearful.btn.secondary Cancel
- form(method='post', action='/stacks/#{data.stack.name}/regions/#{data.name}')#deploy-form
+ form(method='post', action='/stacks/#{data.stack.name}/regions/#{data.region.name}')#deploy-form
p
input(type='text', name='to_revision', size='40', value='#{data.stack.latest_revision}')#to_revision.full_hash
- p !{helpers.buildDiffSegment(data.stack.github_href, data.deployed_revision, data.stack.latest_revision)}
+ p !{helpers.buildDiffSegment(data.stack.github_href, data.region.deployed_revision, data.stack.latest_revision)}
p
input(type='hidden', name='ack_warning', value='#{wmsg ? "false" : "true"}')#wack
input(type='submit', value='Deploy').btn.success
@@ -47,7 +47,7 @@ block content
- each deployment in data.deployments
tr
td
- a(href='/stacks/#{data.stack.name}/regions/#{data.name}/deployments/#{deployment.name}') #{deployment.name}
+ a(href='/stacks/#{data.stack.name}/regions/#{data.region.name}/deployments/#{deployment.name}') #{deployment.name}
td #{helpers.prettyTimeSince(deployment.time)}
td #{deployment.user}
td !{helpers.buildDiffSegment(data.stack.github_href, deployment.from_revision, deployment.to_revision)}
View
1 lib/web/views/layout.jade
@@ -10,7 +10,6 @@ html(lang='en')
script(src='/static/js/jquery-1.7.0.min.js')
script(src='/static/js/bootstrap-modal.js')
script(src='/static/js/dreadnot.js')
- script(src='/socket.io/socket.io.js')
block scripts
body
View
44 static/js/dreadnot.js
@@ -2,13 +2,11 @@
function streamLogs(log) {
- var socket = io.connect(),
- logPath = ['stacks', log.stack, 'regions', log.region, 'deployments', log.deployment, 'log'].join('.'),
- endPath = ['stacks', log.stack, 'regions', log.region, 'deployments', log.deployment, 'end'].join('.');
+ var logPath = ['stacks', log.stack, 'regions', log.region, 'deployments', log.deployment, 'log'].join('/');
+ dest = $('pre.deployment_log');
- socket.on(logPath, function(entry) {
- var dest = $('pre.deployment_log'),
- scroll = Math.abs(dest[0].scrollTop - (dest[0].scrollHeight - dest[0].offsetHeight)) < 10,
+ function pushEntry(entry) {
+ var scroll = Math.abs(dest[0].scrollTop - (dest[0].scrollHeight - dest[0].offsetHeight)) < 10,
line, table;
if (entry.lvl <= 3) {
@@ -39,21 +37,27 @@ function streamLogs(log) {
if (scroll) {
dest[0].scrollTop = dest[0].scrollHeight;
}
- });
-
- socket.on(endPath, function(success) {
- var last = $('pre.deployment_log p').last();
-
- if (success) {
- last.addClass('success');
- } else {
- last.addClass('error');
- }
- });
+ }
+
+ function loadFrom(idx) {
+ $.get('/' + logPath + '?from=' + idx, function(data) {
+ var done = false, success;
+
+ data.forEach(function(entry) {
+ if (typeof entry !== 'boolean') {
+ pushEntry(entry);
+ } else {
+ $('pre.deployment_log p').last().addClass(entry ? 'success' : 'error');
+ }
+ });
+
+ if (!done) {
+ loadFrom(idx + data.length);
+ }
+ });
+ }
- socket.once('connect', function() {
- socket.emit('request log', log);
- });
+ loadFrom(0);
}

0 comments on commit ba64f03

Please sign in to comment.