Skip to content

Commit

Permalink
Refactor bootstrap.py: Move HTTP server initialization to a separate …
Browse files Browse the repository at this point in the history
…class.
  • Loading branch information
chovanecm committed Dec 30, 2017
1 parent 7514112 commit 7d4af0d
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 40 deletions.
2 changes: 1 addition & 1 deletion sacredboard/app/config/jinja_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,6 @@ def detect_alive_experiment(time_difference):
return time_difference < 120


def initialize(app):
def initialize(app, app_config):
"""Register the filters in a Flask application."""
app.register_blueprint(filters)
2 changes: 1 addition & 1 deletion sacredboard/app/webapi/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ def handle_not_found_error(e):
return "Couldn't find resource:\n%s" % e, 404


def initialize(app):
def initialize(app, app_config):
"""Register the module in Flask."""
app.register_blueprint(metrics)
7 changes: 7 additions & 0 deletions sacredboard/app/webapi/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,10 @@ def __call__(self, environ, start_response):
if server:
environ['HTTP_HOST'] = server
return self.app(environ, start_response)


def initialize(app, app_config):
"""Initialize the module."""
sub_url = app_config["http.serve_on_endpoint"]
if sub_url is not "/":
app.wsgi_app = ReverseProxied(app.wsgi_app, script_name=sub_url)
2 changes: 1 addition & 1 deletion sacredboard/app/webapi/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ def handle_tensorboard_unexpected_output(e: process.UnexpectedOutputError):
% (e.output, e.expected), 503


def initialize(app):
def initialize(app, app_config):
"""Register all HTTP endpoints defined in this file."""
app.register_blueprint(routes)
2 changes: 1 addition & 1 deletion sacredboard/app/webapi/runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,6 @@ def handle_not_implemented_error(e: NotImplementedError):
return "Not Implemented: %s" % e, 510


def initialize(app):
def initialize(app, app_config):
"""Register the module in Flask."""
app.register_blueprint(runs)
33 changes: 33 additions & 0 deletions sacredboard/app/webapi/wsgi_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# coding=utf-8
"""Module for starting the WSGI Server and the web application itself."""
from gevent.pywsgi import WSGIServer


class ServerRunner:
"""Sets up the HTTP server (WSGI, if not in debug mode) and runs it."""

def __init__(self):
"""Once initialized, contains the port where the application will listen."""
self.started_on_port = None

def initialize(self, app, app_config):
"""Prepare the server to run and determine the port."""
debug = app_config["debug"]
port = app_config["http.port"]
if debug:
self.started_on_port = port
app.run(host="0.0.0.0", debug=True, port=port)
else:
for port in range(port, port + 50):
self.http_server = WSGIServer(('0.0.0.0', port), app)
try:
self.http_server.start()
except OSError as e:
# try next port
continue
self.started_on_port = port
break

def run_server(self):
"""Start the server."""
self.http_server.serve_forever()
42 changes: 18 additions & 24 deletions sacredboard/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@

import click
from flask import Flask
from gevent.pywsgi import WSGIServer

from sacredboard.app.config import jinja_filters
from sacredboard.app.data.filestorage import FileStorage
from sacredboard.app.data.pymongo import PyMongoDataAccess
from sacredboard.app.webapi import routes, metrics, runs
from sacredboard.app.webapi.proxy import ReverseProxied
from sacredboard.app.webapi import routes, metrics, runs, proxy
from sacredboard.app.webapi.wsgi_server import ServerRunner

locale.setlocale(locale.LC_ALL, '')
app = Flask(__name__)

webapi_modules = [routes, metrics, runs, jinja_filters]
server_runner = ServerRunner()
webapi_modules = [proxy, routes, metrics, runs, jinja_filters, server_runner]


@click.command()
Expand Down Expand Up @@ -108,28 +107,23 @@ def run(debug, no_browser, m, mu, mc, f, port, sub_url):
app.config['DEBUG'] = debug
app.debug = debug

if sub_url is not "/":
app.wsgi_app = ReverseProxied(app.wsgi_app, script_name=sub_url)
app_config = {
"http.serve_on_endpoint": sub_url,
"http.port": port,
"debug": debug
}
_initialize_modules(app_config)
print("Starting sacredboard on port %d" % server_runner.started_on_port)
if not no_browser:
click.launch("http://127.0.0.1:%d" % server_runner.started_on_port)

server_runner.run_server()


def _initialize_modules(app_config):
for module in webapi_modules:
# Initialize Web Api Modules
module.initialize(app)

if debug:
app.run(host="0.0.0.0", debug=True)
else:
for port in range(port, port + 50):
http_server = WSGIServer(('0.0.0.0', port), app)
try:
http_server.start()
except OSError as e:
# try next port
continue
print("Starting sacredboard on port %d" % port)
if not no_browser:
click.launch("http://127.0.0.1:%d" % port)
http_server.serve_forever()
break
module.initialize(app, app_config)


def add_mongo_config(app, simple_connection_string,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
# coding=utf-8
import pytest

import sacredboard.bootstrap as wa
import sacredboard.bootstrap as bootstrap


@pytest.fixture
def app():
return bootstrap.Flask(__name__)


@pytest.fixture()
def app_config():
return {
"http.serve_on_endpoint": "/",
"http.port": 5000,
"debug": False
}

@pytest.mark.parametrize("config_string",
("", "database_name", "789:db_name",
"anotherhost:789:db_name", "bla:bla:bla"))
def test_add_mongo_config(config_string):
app = wa.Flask(__name__)
def test_add_mongo_config(config_string, app):
if config_string == "bla:bla:bla":
with pytest.raises(ValueError):
wa.add_mongo_config_simple(app, config_string, "collection_name")
bootstrap.add_mongo_config_simple(app, config_string, "collection_name")
else:
wa.add_mongo_config_simple(app, config_string, "collection_name")
bootstrap.add_mongo_config_simple(app, config_string, "collection_name")
mongo_client = app.config["data"]
if config_string == "":
assert mongo_client._uri == "mongodb://localhost:27017"
Expand All @@ -30,16 +42,19 @@ def test_add_mongo_config(config_string):


@pytest.mark.parametrize("connection_string", ("mongodb://user:password@192.168.0.1:1234?connectTimeoutMS=300000",
"mongodb://192.168.0.1:1234?connectTimeoutMS=300000"))
def test_add_mongo_config_with_uri(connection_string):
app = wa.Flask(__name__)

wa.add_mongo_config_with_uri(app, connection_string, "db_name", "collection_name")
"mongodb://192.168.0.1:1234?connectTimeoutMS=300000"))
def test_add_mongo_config_with_uri(connection_string, app):
bootstrap.add_mongo_config_with_uri(app, connection_string, "db_name", "collection_name")
mongo_client = app.config["data"]

if connection_string == "mongodb://user:password@192.168.0.1:1234?connectTimeoutMS=300000":
assert mongo_client._uri == "mongodb://user:password@192.168.0.1:1234?connectTimeoutMS=300000"
elif connection_string == "mongodb://192.168.0.1:1234?connectTimeoutMS=300000":
assert mongo_client._uri == "mongodb://192.168.0.1:1234?connectTimeoutMS=300000"

assert (mongo_client._db_name == "db_name")
assert (mongo_client._db_name == "db_name")


def test_module_initialisation_method_call_only(app_config):
"""Only test calling module initialisation to see that no module causes the application to crash"""
bootstrap._initialize_modules(app_config)
2 changes: 1 addition & 1 deletion sacredboard/tests/webapi/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def init_tests():
app.testing = True
app.config["data"] = FakeDataStorage()
test_client = app.test_client()
metrics.initialize(app)
metrics.initialize(app, {})


def test_get_metric():
Expand Down

0 comments on commit 7d4af0d

Please sign in to comment.