Merge branch 'master' of github.com:coreos-inc/quay

This commit is contained in:
Joseph Schorr 2015-02-11 16:23:54 -05:00
commit e9ab7dcd10
11 changed files with 107 additions and 116 deletions

14
app.py
View file

@ -3,7 +3,7 @@ import os
import json import json
import yaml import yaml
from flask import Flask as BaseFlask, Config as BaseConfig, request, Request from flask import Flask as BaseFlask, Config as BaseConfig, request, Request, _request_ctx_stack
from flask.ext.principal import Principal from flask.ext.principal import Principal
from flask.ext.login import LoginManager, UserMixin from flask.ext.login import LoginManager, UserMixin
from flask.ext.mail import Mail from flask.ext.mail import Mail
@ -65,7 +65,6 @@ LICENSE_FILENAME = 'conf/stack/license.enc'
app = Flask(__name__) app = Flask(__name__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
profile = logging.getLogger('profile')
if 'TEST' in os.environ: if 'TEST' in os.environ:
@ -101,21 +100,24 @@ class RequestWithId(Request):
@app.before_request @app.before_request
def _request_start(): def _request_start():
profile.debug('Starting request: %s', request.path) logger.debug('Starting request: %s', request.path)
@app.after_request @app.after_request
def _request_end(r): def _request_end(r):
profile.debug('Ending request: %s', request.path) logger.debug('Ending request: %s', request.path)
return r return r
class InjectingFilter(logging.Filter): class InjectingFilter(logging.Filter):
def filter(self, record): def filter(self, record):
record.msg = '[%s] %s' % (request.request_id, record.msg) if _request_ctx_stack.top is not None:
record.msg = '[%s] %s' % (request.request_id, record.msg)
return True return True
profile.addFilter(InjectingFilter()) # Add the request id filter to all handlers of the root logger
for handler in logging.getLogger().handlers:
handler.addFilter(InjectingFilter())
app.request_class = RequestWithId app.request_class = RequestWithId

View file

@ -11,5 +11,5 @@ import registry
if __name__ == '__main__': if __name__ == '__main__':
logging.config.fileConfig('conf/logging.conf', disable_existing_loggers=False) logging.config.fileConfig('conf/logging_debug.conf', disable_existing_loggers=False)
application.run(port=5000, debug=True, threaded=True, host='0.0.0.0') application.run(port=5000, debug=True, threaded=True, host='0.0.0.0')

View file

@ -3,5 +3,5 @@ workers = 2
worker_class = 'gevent' worker_class = 'gevent'
timeout = 2000 timeout = 2000
daemon = False daemon = False
logconfig = 'conf/logging.conf' logconfig = 'conf/logging_debug.conf'
pythonpath = '.' pythonpath = '.'

View file

@ -1,5 +1,5 @@
[loggers] [loggers]
keys=root, gunicorn.error, gunicorn.access, application.profiler, boto, werkzeug keys=root
[handlers] [handlers]
keys=console keys=console
@ -7,39 +7,9 @@ keys=console
[formatters] [formatters]
keys=generic keys=generic
[logger_application.profiler]
level=DEBUG
handlers=console
propagate=0
qualname=application.profiler
[logger_root] [logger_root]
level=DEBUG
handlers=console
[logger_boto]
level=INFO level=INFO
handlers=console handlers=console
propagate=0
qualname=boto
[logger_werkzeug]
level=DEBUG
handlers=console
propagate=0
qualname=werkzeug
[logger_gunicorn.error]
level=INFO
handlers=console
propagate=1
qualname=gunicorn.error
[logger_gunicorn.access]
level=INFO
handlers=console
propagate=0
qualname=gunicorn.access
[handler_console] [handler_console]
class=StreamHandler class=StreamHandler

21
conf/logging_debug.conf Normal file
View file

@ -0,0 +1,21 @@
[loggers]
keys=root
[handlers]
keys=console
[formatters]
keys=generic
[logger_root]
level=DEBUG
handlers=console
[handler_console]
class=StreamHandler
formatter=generic
args=(sys.stdout, )
[formatter_generic]
format=%(asctime)s [%(process)d] [%(levelname)s] [%(name)s] %(message)s
class=logging.Formatter

View file

@ -13,6 +13,7 @@ proxy_set_header X-Forwarded-For $proxy_protocol_addr;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_redirect off; proxy_redirect off;
proxy_buffer_size 6m;
proxy_set_header Transfer-Encoding $http_transfer_encoding; proxy_set_header Transfer-Encoding $http_transfer_encoding;

View file

@ -16,6 +16,7 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_redirect off; proxy_redirect off;
proxy_buffer_size 6m;
proxy_set_header Transfer-Encoding $http_transfer_encoding; proxy_set_header Transfer-Encoding $http_transfer_encoding;

View file

@ -29,7 +29,6 @@ from endpoints.notificationhelper import spawn_notification
import features import features
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
profile = logging.getLogger('application.profiler')
route_data = None route_data = None
@ -253,7 +252,7 @@ def start_build(repository, dockerfile_id, tags, build_name, subdir, manual,
metadata=metadata, repository=repository) metadata=metadata, repository=repository)
# Add notifications for the build queue. # Add notifications for the build queue.
profile.debug('Adding notifications for repository') logger.debug('Adding notifications for repository')
event_data = { event_data = {
'build_id': build_request.uuid, 'build_id': build_request.uuid,
'build_name': build_name, 'build_name': build_name,

View file

@ -23,7 +23,6 @@ from endpoints.notificationhelper import spawn_notification
import features import features
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
profile = logging.getLogger('application.profiler')
index = Blueprint('index', __name__) index = Blueprint('index', __name__)
@ -120,7 +119,7 @@ def create_user():
else: else:
# New user case # New user case
profile.debug('Creating user') logger.debug('Creating user')
new_user = None new_user = None
try: try:
@ -128,10 +127,10 @@ def create_user():
except model.TooManyUsersException as ex: except model.TooManyUsersException as ex:
abort(402, 'Seat limit has been reached for this license', issue='seat-limit') abort(402, 'Seat limit has been reached for this license', issue='seat-limit')
profile.debug('Creating email code for user') logger.debug('Creating email code for user')
code = model.create_confirm_email_code(new_user) code = model.create_confirm_email_code(new_user)
profile.debug('Sending email code to user') logger.debug('Sending email code to user')
send_confirmation_email(new_user.username, new_user.email, code.code) send_confirmation_email(new_user.username, new_user.email, code.code)
return make_response('Created', 201) return make_response('Created', 201)
@ -168,12 +167,12 @@ def update_user(username):
update_request = request.get_json() update_request = request.get_json()
if 'password' in update_request: if 'password' in update_request:
profile.debug('Updating user password') logger.debug('Updating user password')
model.change_password(get_authenticated_user(), model.change_password(get_authenticated_user(),
update_request['password']) update_request['password'])
if 'email' in update_request: if 'email' in update_request:
profile.debug('Updating user email') logger.debug('Updating user email')
model.update_email(get_authenticated_user(), update_request['email']) model.update_email(get_authenticated_user(), update_request['email'])
return jsonify({ return jsonify({
@ -189,13 +188,13 @@ def update_user(username):
@parse_repository_name @parse_repository_name
@generate_headers(role='write') @generate_headers(role='write')
def create_repository(namespace, repository): def create_repository(namespace, repository):
profile.debug('Parsing image descriptions') logger.debug('Parsing image descriptions')
image_descriptions = json.loads(request.data.decode('utf8')) image_descriptions = json.loads(request.data.decode('utf8'))
profile.debug('Looking up repository') logger.debug('Looking up repository')
repo = model.get_repository(namespace, repository) repo = model.get_repository(namespace, repository)
profile.debug('Repository looked up') logger.debug('Repository looked up')
if not repo and get_authenticated_user() is None: if not repo and get_authenticated_user() is None:
logger.debug('Attempt to create new repository without user auth.') logger.debug('Attempt to create new repository without user auth.')
abort(401, abort(401,
@ -219,11 +218,11 @@ def create_repository(namespace, repository):
issue='no-create-permission', issue='no-create-permission',
namespace=namespace) namespace=namespace)
profile.debug('Creaing repository with owner: %s', get_authenticated_user().username) logger.debug('Creaing repository with owner: %s', get_authenticated_user().username)
repo = model.create_repository(namespace, repository, repo = model.create_repository(namespace, repository,
get_authenticated_user()) get_authenticated_user())
profile.debug('Determining already added images') logger.debug('Determining already added images')
added_images = OrderedDict([(desc['id'], desc) for desc in image_descriptions]) added_images = OrderedDict([(desc['id'], desc) for desc in image_descriptions])
new_repo_images = dict(added_images) new_repo_images = dict(added_images)
@ -239,7 +238,7 @@ def create_repository(namespace, repository):
for existing in existing_images: for existing in existing_images:
added_images.pop(existing.docker_image_id) added_images.pop(existing.docker_image_id)
profile.debug('Creating/Linking necessary images') logger.debug('Creating/Linking necessary images')
username = get_authenticated_user() and get_authenticated_user().username username = get_authenticated_user() and get_authenticated_user().username
translations = {} translations = {}
for image_description in added_images.values(): for image_description in added_images.values():
@ -247,7 +246,7 @@ def create_repository(namespace, repository):
translations, storage.preferred_locations[0]) translations, storage.preferred_locations[0])
profile.debug('Created images') logger.debug('Created images')
track_and_log('push_repo', repo) track_and_log('push_repo', repo)
return make_response('Created', 201) return make_response('Created', 201)
@ -260,14 +259,14 @@ def update_images(namespace, repository):
permission = ModifyRepositoryPermission(namespace, repository) permission = ModifyRepositoryPermission(namespace, repository)
if permission.can(): if permission.can():
profile.debug('Looking up repository') logger.debug('Looking up repository')
repo = model.get_repository(namespace, repository) repo = model.get_repository(namespace, repository)
if not repo: if not repo:
# Make sure the repo actually exists. # Make sure the repo actually exists.
abort(404, message='Unknown repository', issue='unknown-repo') abort(404, message='Unknown repository', issue='unknown-repo')
if get_authenticated_user(): if get_authenticated_user():
profile.debug('Publishing push event') logger.debug('Publishing push event')
username = get_authenticated_user().username username = get_authenticated_user().username
# Mark that the user has pushed the repo. # Mark that the user has pushed the repo.
@ -280,11 +279,11 @@ def update_images(namespace, repository):
event = userevents.get_event(username) event = userevents.get_event(username)
event.publish_event_data('docker-cli', user_data) event.publish_event_data('docker-cli', user_data)
profile.debug('GCing repository') logger.debug('GCing repository')
num_removed = model.garbage_collect_repository(namespace, repository) num_removed = model.garbage_collect_repository(namespace, repository)
# Generate a job for each notification that has been added to this repo # Generate a job for each notification that has been added to this repo
profile.debug('Adding notifications for repository') logger.debug('Adding notifications for repository')
updated_tags = session.get('pushed_tags', {}) updated_tags = session.get('pushed_tags', {})
event_data = { event_data = {
@ -307,13 +306,13 @@ def get_repository_images(namespace, repository):
# TODO invalidate token? # TODO invalidate token?
if permission.can() or model.repository_is_public(namespace, repository): if permission.can() or model.repository_is_public(namespace, repository):
# We can't rely on permissions to tell us if a repo exists anymore # We can't rely on permissions to tell us if a repo exists anymore
profile.debug('Looking up repository') logger.debug('Looking up repository')
repo = model.get_repository(namespace, repository) repo = model.get_repository(namespace, repository)
if not repo: if not repo:
abort(404, message='Unknown repository', issue='unknown-repo') abort(404, message='Unknown repository', issue='unknown-repo')
all_images = [] all_images = []
profile.debug('Retrieving repository images') logger.debug('Retrieving repository images')
for image in model.get_repository_images(namespace, repository): for image in model.get_repository_images(namespace, repository):
new_image_view = { new_image_view = {
'id': image.docker_image_id, 'id': image.docker_image_id,
@ -321,7 +320,7 @@ def get_repository_images(namespace, repository):
} }
all_images.append(new_image_view) all_images.append(new_image_view)
profile.debug('Building repository image response') logger.debug('Building repository image response')
resp = make_response(json.dumps(all_images), 200) resp = make_response(json.dumps(all_images), 200)
resp.mimetype = 'application/json' resp.mimetype = 'application/json'

View file

@ -20,7 +20,6 @@ from util import gzipstream
registry = Blueprint('registry', __name__) registry = Blueprint('registry', __name__)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
profile = logging.getLogger('application.profiler')
class SocketReader(object): class SocketReader(object):
def __init__(self, fp): def __init__(self, fp):
@ -100,12 +99,12 @@ def set_cache_headers(f):
def head_image_layer(namespace, repository, image_id, headers): def head_image_layer(namespace, repository, image_id, headers):
permission = ReadRepositoryPermission(namespace, repository) permission = ReadRepositoryPermission(namespace, repository)
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
if permission.can() or model.repository_is_public(namespace, repository): if permission.can() or model.repository_is_public(namespace, repository):
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
if not repo_image: if not repo_image:
profile.debug('Image not found') logger.debug('Image not found')
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
@ -114,7 +113,7 @@ def head_image_layer(namespace, repository, image_id, headers):
# Add the Accept-Ranges header if the storage engine supports resumable # Add the Accept-Ranges header if the storage engine supports resumable
# downloads. # downloads.
if store.get_supports_resumable_downloads(repo_image.storage.locations): if store.get_supports_resumable_downloads(repo_image.storage.locations):
profile.debug('Storage supports resumable downloads') logger.debug('Storage supports resumable downloads')
extra_headers['Accept-Ranges'] = 'bytes' extra_headers['Accept-Ranges'] = 'bytes'
resp = make_response('') resp = make_response('')
@ -133,35 +132,35 @@ def head_image_layer(namespace, repository, image_id, headers):
def get_image_layer(namespace, repository, image_id, headers): def get_image_layer(namespace, repository, image_id, headers):
permission = ReadRepositoryPermission(namespace, repository) permission = ReadRepositoryPermission(namespace, repository)
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
if permission.can() or model.repository_is_public(namespace, repository): if permission.can() or model.repository_is_public(namespace, repository):
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
if not repo_image: if not repo_image:
profile.debug('Image not found') logger.debug('Image not found')
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
profile.debug('Looking up the layer path') logger.debug('Looking up the layer path')
try: try:
path = store.image_layer_path(repo_image.storage.uuid) path = store.image_layer_path(repo_image.storage.uuid)
profile.debug('Looking up the direct download URL') logger.debug('Looking up the direct download URL')
direct_download_url = store.get_direct_download_url(repo_image.storage.locations, path) direct_download_url = store.get_direct_download_url(repo_image.storage.locations, path)
if direct_download_url: if direct_download_url:
profile.debug('Returning direct download URL') logger.debug('Returning direct download URL')
resp = redirect(direct_download_url) resp = redirect(direct_download_url)
return resp return resp
profile.debug('Streaming layer data') logger.debug('Streaming layer data')
# Close the database handle here for this process before we send the long download. # Close the database handle here for this process before we send the long download.
database.close_db_filter(None) database.close_db_filter(None)
return Response(store.stream_read(repo_image.storage.locations, path), headers=headers) return Response(store.stream_read(repo_image.storage.locations, path), headers=headers)
except (IOError, AttributeError): except (IOError, AttributeError):
profile.exception('Image layer data not found') logger.exception('Image layer data not found')
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
@ -172,30 +171,30 @@ def get_image_layer(namespace, repository, image_id, headers):
@process_auth @process_auth
@extract_namespace_repo_from_session @extract_namespace_repo_from_session
def put_image_layer(namespace, repository, image_id): def put_image_layer(namespace, repository, image_id):
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
permission = ModifyRepositoryPermission(namespace, repository) permission = ModifyRepositoryPermission(namespace, repository)
if not permission.can(): if not permission.can():
abort(403) abort(403)
profile.debug('Retrieving image') logger.debug('Retrieving image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
try: try:
profile.debug('Retrieving image data') logger.debug('Retrieving image data')
uuid = repo_image.storage.uuid uuid = repo_image.storage.uuid
json_data = store.get_content(repo_image.storage.locations, store.image_json_path(uuid)) json_data = store.get_content(repo_image.storage.locations, store.image_json_path(uuid))
except (IOError, AttributeError): except (IOError, AttributeError):
profile.exception('Exception when retrieving image data') logger.exception('Exception when retrieving image data')
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
profile.debug('Retrieving image path info') logger.debug('Retrieving image path info')
layer_path = store.image_layer_path(uuid) layer_path = store.image_layer_path(uuid)
if (store.exists(repo_image.storage.locations, layer_path) and not if (store.exists(repo_image.storage.locations, layer_path) and not
image_is_uploading(repo_image)): image_is_uploading(repo_image)):
exact_abort(409, 'Image already exists') exact_abort(409, 'Image already exists')
profile.debug('Storing layer data') logger.debug('Storing layer data')
input_stream = request.stream input_stream = request.stream
if request.headers.get('transfer-encoding') == 'chunked': if request.headers.get('transfer-encoding') == 'chunked':
@ -262,7 +261,7 @@ def put_image_layer(namespace, repository, image_id):
# The layer is ready for download, send a job to the work queue to # The layer is ready for download, send a job to the work queue to
# process it. # process it.
profile.debug('Adding layer to diff queue') logger.debug('Adding layer to diff queue')
repo = model.get_repository(namespace, repository) repo = model.get_repository(namespace, repository)
image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({ image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({
'namespace_user_id': repo.namespace_user.id, 'namespace_user_id': repo.namespace_user.id,
@ -277,7 +276,7 @@ def put_image_layer(namespace, repository, image_id):
@process_auth @process_auth
@extract_namespace_repo_from_session @extract_namespace_repo_from_session
def put_image_checksum(namespace, repository, image_id): def put_image_checksum(namespace, repository, image_id):
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
permission = ModifyRepositoryPermission(namespace, repository) permission = ModifyRepositoryPermission(namespace, repository)
if not permission.can(): if not permission.can():
abort(403) abort(403)
@ -303,23 +302,23 @@ def put_image_checksum(namespace, repository, image_id):
abort(400, 'Checksum not found in Cookie for image %(image_id)s', abort(400, 'Checksum not found in Cookie for image %(image_id)s',
issue='missing-checksum-cookie', image_id=image_id) issue='missing-checksum-cookie', image_id=image_id)
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
if not repo_image or not repo_image.storage: if not repo_image or not repo_image.storage:
abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id) abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id)
uuid = repo_image.storage.uuid uuid = repo_image.storage.uuid
profile.debug('Looking up repo layer data') logger.debug('Looking up repo layer data')
if not store.exists(repo_image.storage.locations, store.image_json_path(uuid)): if not store.exists(repo_image.storage.locations, store.image_json_path(uuid)):
abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id) abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id)
profile.debug('Marking image path') logger.debug('Marking image path')
if not image_is_uploading(repo_image): if not image_is_uploading(repo_image):
abort(409, 'Cannot set checksum for image %(image_id)s', abort(409, 'Cannot set checksum for image %(image_id)s',
issue='image-write-error', image_id=image_id) issue='image-write-error', image_id=image_id)
profile.debug('Storing image checksum') logger.debug('Storing image checksum')
err = store_checksum(repo_image.storage, checksum) err = store_checksum(repo_image.storage, checksum)
if err: if err:
abort(400, err) abort(400, err)
@ -336,7 +335,7 @@ def put_image_checksum(namespace, repository, image_id):
# The layer is ready for download, send a job to the work queue to # The layer is ready for download, send a job to the work queue to
# process it. # process it.
profile.debug('Adding layer to diff queue') logger.debug('Adding layer to diff queue')
repo = model.get_repository(namespace, repository) repo = model.get_repository(namespace, repository)
image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({ image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({
'namespace_user_id': repo.namespace_user.id, 'namespace_user_id': repo.namespace_user.id,
@ -353,23 +352,23 @@ def put_image_checksum(namespace, repository, image_id):
@require_completion @require_completion
@set_cache_headers @set_cache_headers
def get_image_json(namespace, repository, image_id, headers): def get_image_json(namespace, repository, image_id, headers):
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
permission = ReadRepositoryPermission(namespace, repository) permission = ReadRepositoryPermission(namespace, repository)
if not permission.can() and not model.repository_is_public(namespace, if not permission.can() and not model.repository_is_public(namespace,
repository): repository):
abort(403) abort(403)
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
profile.debug('Looking up repo layer data') logger.debug('Looking up repo layer data')
try: try:
uuid = repo_image.storage.uuid uuid = repo_image.storage.uuid
data = store.get_content(repo_image.storage.locations, store.image_json_path(uuid)) data = store.get_content(repo_image.storage.locations, store.image_json_path(uuid))
except (IOError, AttributeError): except (IOError, AttributeError):
flask_abort(404) flask_abort(404)
profile.debug('Looking up repo layer size') logger.debug('Looking up repo layer size')
size = repo_image.storage.image_size size = repo_image.storage.image_size
headers['X-Docker-Size'] = str(size) headers['X-Docker-Size'] = str(size)
@ -384,16 +383,16 @@ def get_image_json(namespace, repository, image_id, headers):
@require_completion @require_completion
@set_cache_headers @set_cache_headers
def get_image_ancestry(namespace, repository, image_id, headers): def get_image_ancestry(namespace, repository, image_id, headers):
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
permission = ReadRepositoryPermission(namespace, repository) permission = ReadRepositoryPermission(namespace, repository)
if not permission.can() and not model.repository_is_public(namespace, if not permission.can() and not model.repository_is_public(namespace,
repository): repository):
abort(403) abort(403)
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
profile.debug('Looking up image data') logger.debug('Looking up image data')
try: try:
uuid = repo_image.storage.uuid uuid = repo_image.storage.uuid
data = store.get_content(repo_image.storage.locations, store.image_ancestry_path(uuid)) data = store.get_content(repo_image.storage.locations, store.image_ancestry_path(uuid))
@ -401,11 +400,11 @@ def get_image_ancestry(namespace, repository, image_id, headers):
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
profile.debug('Converting to <-> from JSON') logger.debug('Converting to <-> from JSON')
response = make_response(json.dumps(json.loads(data)), 200) response = make_response(json.dumps(json.loads(data)), 200)
response.headers.extend(headers) response.headers.extend(headers)
profile.debug('Done') logger.debug('Done')
return response return response
@ -435,12 +434,12 @@ def store_checksum(image_storage, checksum):
@process_auth @process_auth
@extract_namespace_repo_from_session @extract_namespace_repo_from_session
def put_image_json(namespace, repository, image_id): def put_image_json(namespace, repository, image_id):
profile.debug('Checking repo permissions') logger.debug('Checking repo permissions')
permission = ModifyRepositoryPermission(namespace, repository) permission = ModifyRepositoryPermission(namespace, repository)
if not permission.can(): if not permission.can():
abort(403) abort(403)
profile.debug('Parsing image JSON') logger.debug('Parsing image JSON')
try: try:
data = json.loads(request.data.decode('utf8')) data = json.loads(request.data.decode('utf8'))
except ValueError: except ValueError:
@ -454,10 +453,10 @@ def put_image_json(namespace, repository, image_id):
abort(400, 'Missing key `id` in JSON for image: %(image_id)s', abort(400, 'Missing key `id` in JSON for image: %(image_id)s',
issue='invalid-request', image_id=image_id) issue='invalid-request', image_id=image_id)
profile.debug('Looking up repo image') logger.debug('Looking up repo image')
repo_image = model.get_repo_image_extended(namespace, repository, image_id) repo_image = model.get_repo_image_extended(namespace, repository, image_id)
if not repo_image: if not repo_image:
profile.debug('Image not found') logger.debug('Image not found')
abort(404, 'Image %(image_id)s not found', issue='unknown-image', abort(404, 'Image %(image_id)s not found', issue='unknown-image',
image_id=image_id) image_id=image_id)
@ -471,24 +470,24 @@ def put_image_json(namespace, repository, image_id):
parent_image = None parent_image = None
if parent_id: if parent_id:
profile.debug('Looking up parent image') logger.debug('Looking up parent image')
parent_image = model.get_repo_image_extended(namespace, repository, parent_id) parent_image = model.get_repo_image_extended(namespace, repository, parent_id)
parent_uuid = parent_image and parent_image.storage.uuid parent_uuid = parent_image and parent_image.storage.uuid
parent_locations = parent_image and parent_image.storage.locations parent_locations = parent_image and parent_image.storage.locations
if parent_id: if parent_id:
profile.debug('Looking up parent image data') logger.debug('Looking up parent image data')
if (parent_id and not if (parent_id and not
store.exists(parent_locations, store.image_json_path(parent_uuid))): store.exists(parent_locations, store.image_json_path(parent_uuid))):
abort(400, 'Image %(image_id)s depends on non existing parent image %(parent_id)s', abort(400, 'Image %(image_id)s depends on non existing parent image %(parent_id)s',
issue='invalid-request', image_id=image_id, parent_id=parent_id) issue='invalid-request', image_id=image_id, parent_id=parent_id)
profile.debug('Looking up image storage paths') logger.debug('Looking up image storage paths')
json_path = store.image_json_path(uuid) json_path = store.image_json_path(uuid)
profile.debug('Checking if image already exists') logger.debug('Checking if image already exists')
if (store.exists(repo_image.storage.locations, json_path) and not if (store.exists(repo_image.storage.locations, json_path) and not
image_is_uploading(repo_image)): image_is_uploading(repo_image)):
exact_abort(409, 'Image already exists') exact_abort(409, 'Image already exists')
@ -501,24 +500,24 @@ def put_image_json(namespace, repository, image_id):
command_list = data.get('container_config', {}).get('Cmd', None) command_list = data.get('container_config', {}).get('Cmd', None)
command = json.dumps(command_list) if command_list else None command = json.dumps(command_list) if command_list else None
profile.debug('Setting image metadata') logger.debug('Setting image metadata')
model.set_image_metadata(image_id, namespace, repository, model.set_image_metadata(image_id, namespace, repository,
data.get('created'), data.get('comment'), command, data.get('created'), data.get('comment'), command,
parent_image) parent_image)
profile.debug('Putting json path') logger.debug('Putting json path')
store.put_content(repo_image.storage.locations, json_path, request.data) store.put_content(repo_image.storage.locations, json_path, request.data)
profile.debug('Generating image ancestry') logger.debug('Generating image ancestry')
try: try:
generate_ancestry(image_id, uuid, repo_image.storage.locations, parent_id, parent_uuid, generate_ancestry(image_id, uuid, repo_image.storage.locations, parent_id, parent_uuid,
parent_locations) parent_locations)
except IOError as ioe: except IOError as ioe:
profile.debug('Error when generating ancestry: %s' % ioe.message) logger.debug('Error when generating ancestry: %s' % ioe.message)
abort(404) abort(404)
profile.debug('Done') logger.debug('Done')
return make_response('true', 200) return make_response('true', 200)

View file

@ -6,7 +6,6 @@ from flask import request
from auth.auth_context import get_authenticated_user, get_validated_token, get_validated_oauth_token from auth.auth_context import get_authenticated_user, get_validated_token, get_validated_oauth_token
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
profile = logging.getLogger('application.profiler')
def track_and_log(event_name, repo, **kwargs): def track_and_log(event_name, repo, **kwargs):
repository = repo.name repository = repo.name
@ -23,7 +22,7 @@ def track_and_log(event_name, repo, **kwargs):
authenticated_user = get_authenticated_user() authenticated_user = get_authenticated_user()
authenticated_token = get_validated_token() if not authenticated_user else None authenticated_token = get_validated_token() if not authenticated_user else None
profile.debug('Logging the %s to Mixpanel and the log system', event_name) logger.debug('Logging the %s to Mixpanel and the log system', event_name)
if authenticated_oauth_token: if authenticated_oauth_token:
metadata['oauth_token_id'] = authenticated_oauth_token.id metadata['oauth_token_id'] = authenticated_oauth_token.id
metadata['oauth_token_application_id'] = authenticated_oauth_token.application.client_id metadata['oauth_token_application_id'] = authenticated_oauth_token.application.client_id
@ -45,9 +44,9 @@ def track_and_log(event_name, repo, **kwargs):
} }
# Publish the user event (if applicable) # Publish the user event (if applicable)
profile.debug('Checking publishing %s to the user events system', event_name) logger.debug('Checking publishing %s to the user events system', event_name)
if authenticated_user: if authenticated_user:
profile.debug('Publishing %s to the user events system', event_name) logger.debug('Publishing %s to the user events system', event_name)
user_event_data = { user_event_data = {
'action': event_name, 'action': event_name,
'repository': repository, 'repository': repository,
@ -58,14 +57,14 @@ def track_and_log(event_name, repo, **kwargs):
event.publish_event_data('docker-cli', user_event_data) event.publish_event_data('docker-cli', user_event_data)
# Save the action to mixpanel. # Save the action to mixpanel.
profile.debug('Logging the %s to Mixpanel', event_name) logger.debug('Logging the %s to Mixpanel', event_name)
analytics.track(analytics_id, event_name, extra_params) analytics.track(analytics_id, event_name, extra_params)
# Log the action to the database. # Log the action to the database.
profile.debug('Logging the %s to logs system', event_name) logger.debug('Logging the %s to logs system', event_name)
model.log_action(event_name, namespace, model.log_action(event_name, namespace,
performer=authenticated_user, performer=authenticated_user,
ip=request.remote_addr, metadata=metadata, ip=request.remote_addr, metadata=metadata,
repository=repo) repository=repo)
profile.debug('Track and log of %s complete', event_name) logger.debug('Track and log of %s complete', event_name)