From 84adf680b99bf8d919cf79d15b05c0149a4f6ce6 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 19:10:27 -0400 Subject: [PATCH 01/13] Switch the registry and index to use real s3 and rds. --- config.py | 39 +++++++- data/database.py | 15 ++-- requirements-nover.txt | 3 +- requirements.txt | 1 + storage/__init__.py | 200 +++++++++++++++++++++-------------------- 5 files changed, 154 insertions(+), 104 deletions(-) diff --git a/config.py b/config.py index 136d11945..b6242b116 100644 --- a/config.py +++ b/config.py @@ -1,3 +1,5 @@ +from peewee import MySQLDatabase, SqliteDatabase + class FlaskConfig(object): SECRET_KEY = '1cb18882-6d12-440d-a4cc-b7430fb5f884' @@ -13,5 +15,40 @@ class MailConfig(object): TESTING = False -class ProductionConfig(FlaskConfig, MailConfig): +class SQLiteDB(object): + DB_NAME = 'test.db' + DB_CONNECTION_ARGS = { + 'threadlocals': True + } + DB_DRIVER = SqliteDatabase + + +class RDSMySQL(object): + DB_NAME = 'quay' + DB_CONNECTION_ARGS = { + 'host': 'fluxmonkeylogin.cb0vumcygprn.us-east-1.rds.amazonaws.com', + 'user': 'fluxmonkey', + 'passwd': '8eifM#uoZ85xqC^', + 'threadlocals': True + } + DB_DRIVER = MySQLDatabase + + +class S3Storage(object): + AWS_ACCESS_KEY = 'AKIAJWZWUIS24TWSMWRA' + AWS_SECRET_KEY = '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' + REGISTRY_S3_BUCKET = 'quay-registry' + STORAGE_KIND = 's3' + + +class LocalStorage(object): + STORAGE_KIND = 'local' + LOCAL_STORAGE_DIR = '/tmp/registry' + + +class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB): REGISTRY_SERVER = 'localhost:5000' + + +class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): + REGISTRY_SERVER = 'quay.io' diff --git a/data/database.py b/data/database.py index 13791af53..3a377d02c 100644 --- a/data/database.py +++ b/data/database.py @@ -1,12 +1,15 @@ import string -from random import SystemRandom +from random import SystemRandom +from datetime import datetime from peewee import * from peewee import create_model_tables -from datetime import datetime +from app import app -db = SqliteDatabase('test.db', threadlocals=True) + +db = app.config['DB_DRIVER'](app.config['DB_NAME'], + **app.config['DB_CONNECTION_ARGS']) class BaseModel(Model): @@ -29,7 +32,7 @@ class Repository(BaseModel): namespace = CharField() name = CharField() visibility = ForeignKeyField(Visibility) - description = CharField(null=True) + description = BlobField(null=True) class Meta: database = db @@ -86,11 +89,11 @@ class Image(BaseModel): image_id = CharField() checksum = CharField(null=True) created = DateTimeField(null=True) - comment = CharField(null=True) + comment = BlobField(null=True) repository = ForeignKeyField(Repository) # '/' separated list of ancestory ids, e.g. /1/2/6/7/10/ - ancestors = CharField(index=True, default='/', max_length=65535) + ancestors = CharField(index=True, default='/', max_length=64535) class Meta: database = db diff --git a/requirements-nover.txt b/requirements-nover.txt index 7cdb7d4b6..4f7a3d3b2 100644 --- a/requirements-nover.txt +++ b/requirements-nover.txt @@ -5,4 +5,5 @@ Flask-Principal Flask-Login Flask-Mail python-dateutil -boto \ No newline at end of file +boto +MySQL-python \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2c28e828a..6543f5c24 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ Flask-Mail==0.9.0 Flask-Principal==0.4.0 Jinja2==2.7.1 MarkupSafe==0.18 +MySQL-python==1.2.4 Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 diff --git a/storage/__init__.py b/storage/__init__.py index 2a67815f9..ddcc5948c 100644 --- a/storage/__init__.py +++ b/storage/__init__.py @@ -1,119 +1,123 @@ +import logging import contextlib import tempfile +from app import app + __all__ = ['load'] +logger = logging.getLogger(__name__) class Storage(object): - """Storage is organized as follow: - $ROOT/images/<image_id>/json - $ROOT/images/<image_id>/layer - $ROOT/repositories/<namespace>/<repository_name>/<tag_name> - """ + """Storage is organized as follow: + $ROOT/images/<image_id>/json + $ROOT/images/<image_id>/layer + $ROOT/repositories/<namespace>/<repository_name>/<tag_name> + """ - # Useful if we want to change those locations later without rewriting - # the code which uses Storage - repositories = 'repositories' - images = 'images' - # Set the IO buffer to 64kB - buffer_size = 64 * 1024 + # Useful if we want to change those locations later without rewriting + # the code which uses Storage + repositories = 'repositories' + images = 'images' + # Set the IO buffer to 64kB + buffer_size = 64 * 1024 - #FIXME(samalba): Move all path resolver in each module (out of the base) - def images_list_path(self, namespace, repository): - return '{0}/{1}/{2}/_images_list'.format(self.repositories, - namespace, - repository) + #FIXME(samalba): Move all path resolver in each module (out of the base) + def images_list_path(self, namespace, repository): + return '{0}/{1}/{2}/_images_list'.format(self.repositories, + namespace, + repository) - def image_json_path(self, namespace, repository, image_id): - return '{0}/{1}/{2}/{3}/json'.format(self.images, namespace, - repository, image_id) + def image_json_path(self, namespace, repository, image_id): + return '{0}/{1}/{2}/{3}/json'.format(self.images, namespace, + repository, image_id) - def image_mark_path(self, namespace, repository, image_id): - return '{0}/{1}/{2}/{3}/_inprogress'.format(self.images, namespace, - repository, image_id) + def image_mark_path(self, namespace, repository, image_id): + return '{0}/{1}/{2}/{3}/_inprogress'.format(self.images, namespace, + repository, image_id) - def image_checksum_path(self, namespace, repository, image_id): - return '{0}/{1}/{2}/{3}/_checksum'.format(self.images, namespace, - repository, image_id) + def image_checksum_path(self, namespace, repository, image_id): + return '{0}/{1}/{2}/{3}/_checksum'.format(self.images, namespace, + repository, image_id) - def image_layer_path(self, namespace, repository, image_id): - return '{0}/{1}/{2}/{3}/layer'.format(self.images, namespace, - repository, image_id) + def image_layer_path(self, namespace, repository, image_id): + return '{0}/{1}/{2}/{3}/layer'.format(self.images, namespace, + repository, image_id) - def image_ancestry_path(self, namespace, repository, image_id): - return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace, - repository, image_id) + def image_ancestry_path(self, namespace, repository, image_id): + return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace, + repository, image_id) - def tag_path(self, namespace, repository, tagname=None): - if not tagname: - return '{0}/{1}/{2}'.format(self.repositories, - namespace, - repository) - return '{0}/{1}/{2}/tag_{3}'.format(self.repositories, - namespace, - repository, - tagname) + def tag_path(self, namespace, repository, tagname=None): + if not tagname: + return '{0}/{1}/{2}'.format(self.repositories, + namespace, + repository) + return '{0}/{1}/{2}/tag_{3}'.format(self.repositories, + namespace, + repository, + tagname) - def index_images_path(self, namespace, repository): - return '{0}/{1}/{2}/_index_images'.format(self.repositories, - namespace, - repository) + def index_images_path(self, namespace, repository): + return '{0}/{1}/{2}/_index_images'.format(self.repositories, + namespace, + repository) - def get_content(self, path): - raise NotImplementedError + def get_content(self, path): + raise NotImplementedError - def put_content(self, path, content): - raise NotImplementedError + def put_content(self, path, content): + raise NotImplementedError - def stream_read(self, path): - raise NotImplementedError + def stream_read(self, path): + raise NotImplementedError - def stream_write(self, path, fp): - raise NotImplementedError + def stream_write(self, path, fp): + raise NotImplementedError - def list_directory(self, path=None): - raise NotImplementedError + def list_directory(self, path=None): + raise NotImplementedError - def exists(self, path): - raise NotImplementedError + def exists(self, path): + raise NotImplementedError - def remove(self, path): - raise NotImplementedError + def remove(self, path): + raise NotImplementedError - def get_size(self, path): - raise NotImplementedError + def get_size(self, path): + raise NotImplementedError @contextlib.contextmanager def store_stream(stream): - """Stores the entire stream to a temporary file.""" - tmpf = tempfile.TemporaryFile() - while True: - try: - buf = stream.read(4096) - if not buf: - break - tmpf.write(buf) - except IOError: - break - tmpf.seek(0) - yield tmpf - tmpf.close() + """Stores the entire stream to a temporary file.""" + tmpf = tempfile.TemporaryFile() + while True: + try: + buf = stream.read(4096) + if not buf: + break + tmpf.write(buf) + except IOError: + break + tmpf.seek(0) + yield tmpf + tmpf.close() def temp_store_handler(): - tmpf = tempfile.TemporaryFile() + tmpf = tempfile.TemporaryFile() - def fn(buf): - try: - tmpf.write(buf) - except IOError: - pass + def fn(buf): + try: + tmpf.write(buf) + except IOError: + pass - return tmpf, fn + return tmpf, fn from local import LocalStorage @@ -124,20 +128,24 @@ _storage = {} def load(kind=None): - """Returns the right storage class according to the configuration.""" - global _storage + """Returns the right storage class according to the configuration.""" + global _storage - # TODO hard code to local for now - kind = 'local' - # if not kind: - # kind = cfg.storage.lower() - if kind in _storage: - return _storage[kind] - if kind == 's3': - store = S3Storage('/registry', 'access_key', 'secret_key', 'bucket') - elif kind == 'local': - store = LocalStorage('/tmp/registry') - else: - raise ValueError('Not supported storage \'{0}\''.format(kind)) - _storage[kind] = store - return store + # TODO hard code to local for now + kind = app.config['STORAGE_KIND'] + # if not kind: + # kind = cfg.storage.lower() + if kind in _storage: + return _storage[kind] + if kind == 's3': + logger.debug('Using s3 storage.') + store = S3Storage('', app.config['AWS_ACCESS_KEY'], + app.config['AWS_SECRET_KEY'], + app.config['REGISTRY_S3_BUCKET']) + elif kind == 'local': + logger.debug('Using local storage.') + store = LocalStorage(app.config['LOCAL_STORAGE_DIR']) + else: + raise ValueError('Not supported storage \'{0}\''.format(kind)) + _storage[kind] = store + return store From 22edde9cb4c4820c94dfffe3eaffd56580128da7 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 19:28:51 -0400 Subject: [PATCH 02/13] It was the distribute library not mysql causing problems. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6543f5c24..6a05826f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.34 +distribute==0.6.27 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From ab1305d728291f2b4e95019b8ffbc529bef5cd52 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 19:33:32 -0400 Subject: [PATCH 03/13] Going to try rebuilding the environment. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6a05826f5..d508a85c0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.27 +distribute==0.6.28 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From 8f554c51d0c45322539c5c2549a33b3a98f05bb2 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 19:48:17 -0400 Subject: [PATCH 04/13] Try downgrading both distribute and mysql. --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d508a85c0..4bc49b6ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,12 +4,12 @@ Flask-Mail==0.9.0 Flask-Principal==0.4.0 Jinja2==2.7.1 MarkupSafe==0.18 -MySQL-python==1.2.4 +MySQL-python==1.2.3 Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.28 +distribute==0.6.27 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From 705624dd6f60340244bc7f9b89193b77886a6c4d Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 19:55:00 -0400 Subject: [PATCH 05/13] Try install mysql-python through yum. --- .ebextensions/python27.config | 1 + requirements.txt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.ebextensions/python27.config b/.ebextensions/python27.config index 0d7b06efb..e474fbea3 100644 --- a/.ebextensions/python27.config +++ b/.ebextensions/python27.config @@ -7,6 +7,7 @@ packages: python27-devel: [] make: [] httpd-devel: [] + MySQL-python: [] commands: # The modwsgi version currently installed on the system diff --git a/requirements.txt b/requirements.txt index 4bc49b6ff..d508a85c0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,12 +4,12 @@ Flask-Mail==0.9.0 Flask-Principal==0.4.0 Jinja2==2.7.1 MarkupSafe==0.18 -MySQL-python==1.2.3 +MySQL-python==1.2.4 Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.27 +distribute==0.6.28 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From 2e3c4723d05af16f574155301abcbaf60463484d Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 20:04:32 -0400 Subject: [PATCH 06/13] I'm losing my mind here. This needs to start working. --- .ebextensions/python27.config | 1 - requirements.txt | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.ebextensions/python27.config b/.ebextensions/python27.config index e474fbea3..0d7b06efb 100644 --- a/.ebextensions/python27.config +++ b/.ebextensions/python27.config @@ -7,7 +7,6 @@ packages: python27-devel: [] make: [] httpd-devel: [] - MySQL-python: [] commands: # The modwsgi version currently installed on the system diff --git a/requirements.txt b/requirements.txt index d508a85c0..71049adb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,12 +4,11 @@ Flask-Mail==0.9.0 Flask-Principal==0.4.0 Jinja2==2.7.1 MarkupSafe==0.18 -MySQL-python==1.2.4 +MySQL-python==1.2.3 Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.28 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From f8f86bcb04972673f96c9c8d364713476c8ade18 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 20:13:36 -0400 Subject: [PATCH 07/13] Try to upgrade distribute prior to the app running. --- .ebextensions/python27.config | 3 +++ requirements.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/.ebextensions/python27.config b/.ebextensions/python27.config index 0d7b06efb..717384315 100644 --- a/.ebextensions/python27.config +++ b/.ebextensions/python27.config @@ -23,6 +23,9 @@ commands: command: grep "python2.7" 03deploy.py || sed -i 's/--distribute/--python=python2.7 &/' 03deploy.py cwd: /opt/elasticbeanstalk/hooks/appdeploy/pre + updatedistribute: + command: easy_install -U distribute + container_commands: # Now that our app is installed using python2.7 we # need to fix some paths that the wsgi configuration diff --git a/requirements.txt b/requirements.txt index 71049adb4..321bcc6c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 +distribute==0.6.28 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From 52db1c87961eff6a08c2130d627fe9ce3d26e8f5 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 20:26:41 -0400 Subject: [PATCH 08/13] Try using pymysql instead of mysqldb. --- .ebextensions/python27.config | 3 --- requirements-nover.txt | 2 +- requirements.txt | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.ebextensions/python27.config b/.ebextensions/python27.config index 717384315..0d7b06efb 100644 --- a/.ebextensions/python27.config +++ b/.ebextensions/python27.config @@ -23,9 +23,6 @@ commands: command: grep "python2.7" 03deploy.py || sed -i 's/--distribute/--python=python2.7 &/' 03deploy.py cwd: /opt/elasticbeanstalk/hooks/appdeploy/pre - updatedistribute: - command: easy_install -U distribute - container_commands: # Now that our app is installed using python2.7 we # need to fix some paths that the wsgi configuration diff --git a/requirements-nover.txt b/requirements-nover.txt index 4f7a3d3b2..9a45a60cd 100644 --- a/requirements-nover.txt +++ b/requirements-nover.txt @@ -6,4 +6,4 @@ Flask-Login Flask-Mail python-dateutil boto -MySQL-python \ No newline at end of file +pymysql \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 321bcc6c1..c442ed8c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,12 +4,11 @@ Flask-Mail==0.9.0 Flask-Principal==0.4.0 Jinja2==2.7.1 MarkupSafe==0.18 -MySQL-python==1.2.3 +PyMySQL==0.5 Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 boto==2.13.3 -distribute==0.6.28 itsdangerous==0.23 peewee==2.1.4 py-bcrypt==0.4 From abd4e8a7ab6feaf33be16a4d1cd17245d3d1e934 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 23:18:05 -0400 Subject: [PATCH 09/13] Fix search by removing description as a searched field. --- data/model.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data/model.py b/data/model.py index c70013b9b..31a432b88 100644 --- a/data/model.py +++ b/data/model.py @@ -112,9 +112,7 @@ def get_visible_repositories(username=None): def get_matching_repositories(repo_term, username=None): visible = get_visible_repositories(username) search_clauses = (Repository.name ** ('%' + repo_term + '%') | - Repository.namespace ** ('%' + repo_term + '%') | - Repository.description ** ('%' + repo_term + '%')) - + Repository.namespace ** ('%' + repo_term + '%')) final = visible.where(search_clauses).limit(10) return list(final) From 25c4054c1935a54e85b8843765b2a0f270ae1268 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 23:22:52 -0400 Subject: [PATCH 10/13] Long description fields should have been text rather than blob. --- data/database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/database.py b/data/database.py index 3a377d02c..6607a4751 100644 --- a/data/database.py +++ b/data/database.py @@ -32,7 +32,7 @@ class Repository(BaseModel): namespace = CharField() name = CharField() visibility = ForeignKeyField(Visibility) - description = BlobField(null=True) + description = TextField(null=True) class Meta: database = db @@ -89,7 +89,7 @@ class Image(BaseModel): image_id = CharField() checksum = CharField(null=True) created = DateTimeField(null=True) - comment = BlobField(null=True) + comment = TextField(null=True) repository = ForeignKeyField(Repository) # '/' separated list of ancestory ids, e.g. /1/2/6/7/10/ From 67147240b697df50c4c86c76996e9b9f6d8f583f Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Mon, 30 Sep 2013 23:54:12 -0400 Subject: [PATCH 11/13] Use production config in production and dev config in dev. --- .ebextensions/python27.config | 4 +++- app.py | 8 ++++++-- application.py | 6 ++---- config.py | 18 +++++++++++++++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.ebextensions/python27.config b/.ebextensions/python27.config index 0d7b06efb..4ca890223 100644 --- a/.ebextensions/python27.config +++ b/.ebextensions/python27.config @@ -35,4 +35,6 @@ container_commands: option_settings: "aws:elasticbeanstalk:container:python:staticfiles": - "/static": "static/" \ No newline at end of file + "/static": "static/" + "aws:elasticbeanstalk:application:environment": + "STACK": "prod" diff --git a/app.py b/app.py index ea52822ee..88a445436 100644 --- a/app.py +++ b/app.py @@ -1,13 +1,17 @@ import logging +import os from flask import Flask from flask.ext.principal import Principal from flask.ext.login import LoginManager from flask.ext.mail import Mail -from config import ProductionConfig +from config import ProductionConfig, DebugConfig app = Flask(__name__) -app.config.from_object(ProductionConfig()) + +is_prod = os.environ.get('STACK', '').strip().lower().startswith('prod') +config_object = ProductionConfig() if is_prod else DebugConfig() +app.config.from_object(config_object) logger = logging.getLogger(__name__) diff --git a/application.py b/application.py index c4e4f602e..8dca9ef9c 100644 --- a/application.py +++ b/application.py @@ -11,9 +11,7 @@ import endpoints.registry # Remove this for prod config application.debug = True -if __name__ == '__main__': - FORMAT = '%(asctime)-15s - %(levelname)s - %(pathname)s - ' + \ - '%(funcName)s - %(message)s' - logging.basicConfig(format=FORMAT, level=logging.DEBUG) +logging.basicConfig(**application.config['LOGGING_CONFIG']) +if __name__ == '__main__': application.run(port=5001, debug=True) diff --git a/config.py b/config.py index b6242b116..a786e8ecc 100644 --- a/config.py +++ b/config.py @@ -1,5 +1,12 @@ +import logging + from peewee import MySQLDatabase, SqliteDatabase + +LOG_FORMAT = '%(asctime)-15s - %(levelname)s - %(pathname)s - ' + \ + '%(funcName)s - %(message)s' + + class FlaskConfig(object): SECRET_KEY = '1cb18882-6d12-440d-a4cc-b7430fb5f884' @@ -29,7 +36,7 @@ class RDSMySQL(object): 'host': 'fluxmonkeylogin.cb0vumcygprn.us-east-1.rds.amazonaws.com', 'user': 'fluxmonkey', 'passwd': '8eifM#uoZ85xqC^', - 'threadlocals': True + 'threadlocals': True, } DB_DRIVER = MySQLDatabase @@ -48,7 +55,16 @@ class LocalStorage(object): class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB): REGISTRY_SERVER = 'localhost:5000' + LOGGING_CONFIG = { + 'level': logging.DEBUG, + 'format': LOG_FORMAT + } class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): REGISTRY_SERVER = 'quay.io' + LOGGING_CONFIG = { + 'filename': '/opt/python/log/application.log', + 'level': logging.DEBUG, + 'format': LOG_FORMAT, + } From afb5dbaaa49117a0f8eacbad4853bfb0761bdbdc Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Tue, 1 Oct 2013 00:16:03 -0400 Subject: [PATCH 12/13] Try logging to stderr. --- config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.py b/config.py index a786e8ecc..77240544e 100644 --- a/config.py +++ b/config.py @@ -1,4 +1,5 @@ import logging +import sys from peewee import MySQLDatabase, SqliteDatabase @@ -64,7 +65,7 @@ class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB): class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL): REGISTRY_SERVER = 'quay.io' LOGGING_CONFIG = { - 'filename': '/opt/python/log/application.log', + 'stream': sys.stderr, 'level': logging.DEBUG, 'format': LOG_FORMAT, } From 2a9a8635b685eb073496c5591f0b6e30d9483105 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Tue, 1 Oct 2013 00:23:40 -0400 Subject: [PATCH 13/13] We must pass authorization headers to our WSGI app. --- wsgi.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/wsgi.conf b/wsgi.conf index 0ab627d81..3671e593f 100644 --- a/wsgi.conf +++ b/wsgi.conf @@ -3,6 +3,7 @@ LoadModule wsgi_module modules/mod_wsgi.so WSGIPythonHome /opt/python/run/venv WSGISocketPrefix run/wsgi WSGIRestrictEmbedded On +WSGIPassAuthorization On <VirtualHost *:80>