Skip to content

Commit

Permalink
Rearrange proxying so that apps find their proxy themselves.
Browse files Browse the repository at this point in the history
  • Loading branch information
Naomi Seyfer committed Jun 13, 2013
1 parent 213cd94 commit bd53fbe
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 30 deletions.
28 changes: 22 additions & 6 deletions packages/ctl/ctl.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,31 @@ Ctl.Commands.push({
var appConfig = Ctl.prettyCall(
Ctl.findGalaxy(), 'getAppConfiguration', [Ctl.myAppName()]);

var proxyConfig;
var bindPathPrefix = "";
if (appConfig.admin) {
bindPathPrefix = "/" + Ctl.myAppName();
proxyConfig = {
securePort: 44433,
insecurePort: 9414,
unprivilegedPorts: true,
bindHost: "localhost",
bindPathPrefix: bindPathPrefix,
omitSsl: true
};
} else {
proxyConfig = {
bindHost: appConfig.sitename,
// XXX eventually proxy should be privileged
unprivilegedPorts: true
};
}

var deployConfig = {
boot: {
bind: {
// XXX hardcode proxy location
viaProxy: {
proxyEndpoint: "localhost:3500",
bindHost: appConfig.sitename,
// XXX eventually proxy should be privileged
unprivilegedPorts: true
}
viaProxy: proxyConfig
}
},
packages: {
Expand All @@ -55,6 +70,7 @@ Ctl.Commands.push({
exitPolicy: 'restart',
env: {
METEOR_DEPLOY_CONFIG: JSON.stringify(deployConfig),
PATH_PREFIX: bindPathPrefix,
ROOT_URL: appConfig.sitename
},
ports: {
Expand Down
4 changes: 2 additions & 2 deletions packages/livedata/stream_client_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ var translateUrl = function(url, newSchemeBase, subPath) {
url = newSchemeBase + "://" + url;
}

if (__meteor_runtime_config__.ABSOLUTE_URL && startsWith(url, "/"))
url = Meteor.absoluteUrl() + url;
if (__meteor_runtime_config__.PATH_PREFIX && startsWith(url, "/"))
url = __meteor_runtime_config__.PATH_PREFIX + url;

if (endsWith(url, "/"))
return url + subPath;
Expand Down
4 changes: 2 additions & 2 deletions packages/meteor/url_server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
if (process.env.ROOT_URL &&
typeof __meteor_runtime_config__ === "object")
__meteor_runtime_config__.ROOT_URL = process.env.ROOT_URL;
if (process.env.ABSOLUTE_URL &&
if (process.env.PATH_PREFIX &&
typeof __meteor_runtime_config__ === "object")
__meteor_runtime_config__.ABSOLUTE_URL = true;
__meteor_runtime_config__.PATH_PREFIX = process.env.PATH_PREFIX;
3 changes: 2 additions & 1 deletion packages/webapp/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Npm.depends({connect: "2.7.10",
useragent: "2.0.1"});

Package.on_use(function (api) {
api.use(['underscore'], 'server');
// XXX: Refactor so as not to have to use ctl-helper
api.use(['logging', 'underscore'], 'server');
api.add_files('webapp_server.js', 'server');
});
48 changes: 40 additions & 8 deletions packages/webapp/webapp_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ var useragent = Npm.require('useragent');
// pidfiles.
// XXX This should really be part of the boot script, not the webapp package.
// Or we should just get rid of it, and rely on containerization.


var findGalaxy = _.once(function () {
if (!('GALAXY' in process.env)) {
console.log(
"GALAXY environment variable must be set. See 'galaxy --help'.");
process.exit(1);
}

return Meteor.connect(process.env['GALAXY']);
});


var initKeepalive = function () {
var keepaliveCount = 0;

Expand Down Expand Up @@ -239,13 +252,11 @@ var runWebAppServer = function () {
"// ##RUNTIME_CONFIG##",
"__meteor_runtime_config__ = " +
JSON.stringify(__meteor_runtime_config__) + ";");
var rootUrl = "";
if (process.env.ABSOLUTE_URL) {
rootUrl = __meteor_runtime_config__.ROOT_URL || process.env.ROOT_URL;
}

var pathPrefix = __meteor_runtime_config__.PATH_PREFIX || process.env.PATH_PREFIX || "";
boilerplateHtml = boilerplateHtml.replace(
/##ROOT_URL##/g,
rootUrl
/##PATH_PREFIX##/g,
pathPrefix
);

app.use(function (req, res, next) {
Expand Down Expand Up @@ -274,8 +285,28 @@ var runWebAppServer = function () {
if (argv.keepalive)
console.log("LISTENING"); // must match run.js
var port = httpServer.address().port;
if (bind.viaProxy) {
if (bind.viaProxy && bind.viaProxy.proxyEndpoint) {
bindToProxy(bind.viaProxy);
} else if (bind.viaProxy) {
// bind via the proxy, but we'll have to find it ourselves via
// ultraworld.
var galaxy = findGalaxy();
galaxy.subscribe('servicesByName', 'proxy');
var Proxies = new Meteor.Collection('services', {
manager: galaxy
});
var doBinding = function (proxyService) {
if (proxyService.providers.proxy) {
Log("Attempting to bind to proxy");
bindToProxy(_.extend({
proxyEndpoint: proxyService.providers.proxy
}, bind.viaProxy));
}
};
Proxies.find().observe({
added: doBinding,
changed: doBinding
});
}

_.each(__meteor_bootstrap__.postStartupHooks, function (x) { x(); });
Expand Down Expand Up @@ -364,8 +395,9 @@ var bindToProxy = Meteor._bindToProxy = function (proxyConfig) {
host: host,
port: port
}
});
});
}
Log("Bound to proxy");
};

runWebAppServer();
4 changes: 2 additions & 2 deletions tools/app.html.in
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<!DOCTYPE html>
<html##HTML_ATTRIBUTES##>
<head>
{{#each stylesheets}} <link rel="stylesheet" href="##ROOT_URL##{{this}}">
{{#each stylesheets}} <link rel="stylesheet" href="##PATH_PREFIX##{{this}}">
{{/each}}

<script type="text/javascript">
// ##RUNTIME_CONFIG##
</script>

{{#each scripts}} <script type="text/javascript" src="##ROOT_URL##{{this}}"></script>
{{#each scripts}} <script type="text/javascript" src="##PATH_PREFIX##{{this}}"></script>
{{/each}}

{{{head_extra}}}
Expand Down
18 changes: 11 additions & 7 deletions tools/deploy-galaxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,18 @@ exports.deploy = function (options) {
// - app
// - streaming (BOOL)
exports.logs = function (options) {
var galaxy = getGalaxy(options.context);
var logReaderURL = prettyCall(galaxy, "getLogReaderURL", [], {
'no-log-reader': "Can't find log reader service"
});

var logReader = getMeteor().connect(logReaderURL);
var logReaderURL;
if (options.context.adminBaseUrl) {
logReaderURL = options.context.adminBaseUrl + "log-reader";
} else {
var galaxy = getGalaxy(options.context);
logReaderURL = prettyCall(galaxy, "getLogReaderURL", [], {
'no-log-reader': "Can't find log reader service"
});
galaxy.close();
}

var logReader = getMeteor(options.context).connect(logReaderURL);
var Log = unipackage.load({
library: options.context.library,
packages: [ 'logging' ],
Expand Down Expand Up @@ -220,7 +225,6 @@ exports.logs = function (options) {
if (!options.streaming) {
// Close connections to Galaxy and log-reader
// (otherwise Node will continue running).
galaxy.close();
logReader.close();
}
};
84 changes: 82 additions & 2 deletions tools/meteor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Fiber(function () {
var path = require('path');
var _ = require('underscore');
var fs = require("fs");
var cp = require('child_process');
var files = require('./files.js');
var deploy = require('./deploy.js');
var runner = require('./run.js');
Expand All @@ -19,6 +20,46 @@ Fiber(function () {
var warehouse = require('./warehouse.js');
var logging = require('./logging.js');


var Future = require('fibers/future');

var sshTunnel = function (to, localPort, remoteEnd, keyfile) {
var args = [to, '-L', localPort+':'+remoteEnd, 'echo __CONNECTED__ && cat -'];
if (keyfile)
args = ["-i", keyfile].concat(args);
var tunnel = cp.spawn('ssh', args, {
stdio: [process.stdin, 'pipe', 'pipe']
});

var exitFuture = new Future();
var connectedFuture = new Future();

tunnel.on('exit', function (code, signal) {
if (!connectedFuture.isResolved()) {
connectedFuture.throw(new Error("ssh exited without making a connection"));
}
exitFuture.return(signal || code);
});

tunnel.stdout.setEncoding('utf8');
tunnel.stdout.on('data', function (str) {
if (!connectedFuture.isResolved() && str.match(/__CONNECTED__/)) {
connectedFuture.return(true);
}
});

tunnel.stderr.setEncoding('utf8');
tunnel.stderr.on('data', function (str) {
if (str.match(/Killed by/))
return;
process.stderr.write(str);
});

tunnel.waitExit = _.bind(exitFuture.wait, exitFuture);
tunnel.waitConnected = _.bind(connectedFuture.wait, connectedFuture);
return tunnel;
};

// This code is duplicated in app/server/server.js.
var MIN_NODE_VERSION = 'v0.8.24';
if (require('semver').lt(process.version, MIN_NODE_VERSION)) {
Expand Down Expand Up @@ -58,7 +99,15 @@ Fiber(function () {
// Figures out if we're in an app dir, what release we're using, etc. May
// download the release if necessary.
var calculateContext = function (argv) {
context.galaxy = process.env['GALAXY'];
context.port = process.env.PORT || 9414;
if (!!process.env.GALAXY && process.env.GALAXY.indexOf("ssh://") === 0) {
context.galaxy = "localhost:" + context.port + "/ultraworld";
context.adminBaseUrl = "localhost:" + context.port + "/";
context.galaxyHost = process.env.GALAXY.substr("ssh://".length);
context.identity = argv.identity;
} else {
context.galaxy = process.env.GALAXY;
}

var appDir = files.findAppDir();
context.appDir = appDir && path.resolve(appDir);
Expand Down Expand Up @@ -258,6 +307,23 @@ Fiber(function () {
}
});

Commands.push({
name: "galaxy",
help: "Interact with your galaxy server",
func: function (argv) {
var cmd = argv._.splice(0, 1)[0];
switch (cmd) {
case "configure":
console.log("Visit http://localhost:" + context.port + "/proxy to configure your galaxy");
var fut = new Future();
fut.wait();
break;
default:
break;
}
}
});

Commands.push({
name: "help",
func: function (argv) {
Expand Down Expand Up @@ -751,6 +817,8 @@ Fiber(function () {
.boolean('debug')
.describe('debug', 'deploy in debug mode (don\'t minify, etc)')
.describe('settings', 'set optional data for Meteor.settings')
.alias('identity', 'i')
.describe('identity', 'Selects a file from which the identity (private key) is read. See ssh(1) for details.')
.describe('star', 'a star (tarball) to deploy instead of the current meteor app')
.usage(
"Usage: meteor deploy <site> [--password] [--settings settings.json] [--debug] [--delete]\n" +
Expand Down Expand Up @@ -1251,7 +1319,19 @@ Fiber(function () {
if (PROFILE_REQUIRE)
require('./profile-require.js').printReport();

findCommand(cmd).func(argv);
var tunnel;
try {
if (context.galaxyHost) {
tunnel = sshTunnel(context.galaxyHost, context.port, "localhost:9414", context.identity);
tunnel.waitConnected();
}
findCommand(cmd).func(argv);
} finally {
if (tunnel) {
tunnel.kill('SIGHUP');
tunnel.waitExit();
}
}
};

main();
Expand Down

0 comments on commit bd53fbe

Please sign in to comment.