Accidental refactor, split out legacy.py into separate sumodules and update all call sites.
This commit is contained in:
parent
2109d24483
commit
3efaa255e8
92 changed files with 4458 additions and 4269 deletions
|
@ -26,4 +26,4 @@ def ping():
|
|||
|
||||
from endpoints.v1 import index
|
||||
from endpoints.v1 import registry
|
||||
from endpoints.v1 import tags
|
||||
from endpoints.v1 import tag
|
|
@ -2,20 +2,17 @@ import json
|
|||
import logging
|
||||
import urlparse
|
||||
|
||||
from flask import request, make_response, jsonify, session, Blueprint
|
||||
from flask import request, make_response, jsonify, session
|
||||
from functools import wraps
|
||||
from collections import OrderedDict
|
||||
|
||||
from data import model
|
||||
from data.model import oauth
|
||||
from app import app, authentication, userevents, storage
|
||||
from auth.auth import process_auth, generate_signed_token
|
||||
from auth.auth_context import get_authenticated_user, get_validated_token, get_validated_oauth_token
|
||||
from util.names import parse_repository_name
|
||||
from util.useremails import send_confirmation_email
|
||||
from auth.permissions import (ModifyRepositoryPermission, UserAdminPermission,
|
||||
ReadRepositoryPermission, CreateRepositoryPermission,
|
||||
AlwaysFailPermission, repository_read_grant, repository_write_grant)
|
||||
repository_read_grant, repository_write_grant)
|
||||
|
||||
from util.http import abort
|
||||
from endpoints.v1 import v1_bp
|
||||
|
@ -23,8 +20,6 @@ from endpoints.trackhelper import track_and_log
|
|||
from endpoints.notificationhelper import spawn_notification
|
||||
from endpoints.decorators import anon_protect, anon_allowed
|
||||
|
||||
import features
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -90,13 +85,13 @@ def create_user():
|
|||
|
||||
if username == '$token':
|
||||
try:
|
||||
model.load_token_data(password)
|
||||
model.token.load_token_data(password)
|
||||
return success
|
||||
except model.InvalidTokenException:
|
||||
abort(400, 'Invalid access token.', issue='invalid-access-token')
|
||||
|
||||
elif username == '$oauthtoken':
|
||||
validated = oauth.validate_access_token(password)
|
||||
validated = model.oauth.validate_access_token(password)
|
||||
if validated is not None:
|
||||
return success
|
||||
else:
|
||||
|
@ -104,7 +99,7 @@ def create_user():
|
|||
|
||||
elif '+' in username:
|
||||
try:
|
||||
model.verify_robot(username, password)
|
||||
model.user.verify_robot(username, password)
|
||||
return success
|
||||
except model.InvalidRobotException:
|
||||
abort(400, 'Invalid robot account or password.',
|
||||
|
@ -157,12 +152,11 @@ def update_user(username):
|
|||
|
||||
if 'password' in update_request:
|
||||
logger.debug('Updating user password')
|
||||
model.change_password(get_authenticated_user(),
|
||||
update_request['password'])
|
||||
model.user.change_password(get_authenticated_user(), update_request['password'])
|
||||
|
||||
if 'email' in update_request:
|
||||
logger.debug('Updating user email')
|
||||
model.update_email(get_authenticated_user(), update_request['email'])
|
||||
model.user.update_email(get_authenticated_user(), update_request['email'])
|
||||
|
||||
return jsonify({
|
||||
'username': get_authenticated_user().username,
|
||||
|
@ -178,11 +172,8 @@ def update_user(username):
|
|||
@generate_headers(scope=GrantType.WRITE_REPOSITORY, add_grant_for_status=201)
|
||||
@anon_allowed
|
||||
def create_repository(namespace, repository):
|
||||
logger.debug('Parsing image descriptions for repository %s/%s', namespace, repository)
|
||||
image_descriptions = json.loads(request.data.decode('utf8'))
|
||||
|
||||
logger.debug('Looking up repository %s/%s', namespace, repository)
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
|
||||
logger.debug('Found repository %s/%s', namespace, repository)
|
||||
if not repo and get_authenticated_user() is None:
|
||||
|
@ -201,18 +192,16 @@ def create_repository(namespace, repository):
|
|||
else:
|
||||
permission = CreateRepositoryPermission(namespace)
|
||||
if not permission.can():
|
||||
logger.info('Attempt to create a new repo %s/%s with insufficient perms', namespace, repository)
|
||||
abort(403,
|
||||
message='You do not have permission to create repositories in namespace "%(namespace)s"',
|
||||
issue='no-create-permission',
|
||||
namespace=namespace)
|
||||
logger.info('Attempt to create a new repo %s/%s with insufficient perms', namespace,
|
||||
repository)
|
||||
msg = 'You do not have permission to create repositories in namespace "%(namespace)s"'
|
||||
abort(403, message=msg, issue='no-create-permission', namespace=namespace)
|
||||
|
||||
# Attempt to create the new repository.
|
||||
logger.debug('Creating repository %s/%s with owner: %s', namespace, repository,
|
||||
get_authenticated_user().username)
|
||||
|
||||
repo = model.create_repository(namespace, repository,
|
||||
get_authenticated_user())
|
||||
repo = model.repository.create_repository(namespace, repository, get_authenticated_user())
|
||||
|
||||
if get_authenticated_user():
|
||||
user_event_data = {
|
||||
|
@ -237,13 +226,13 @@ def update_images(namespace, repository):
|
|||
|
||||
if permission.can():
|
||||
logger.debug('Looking up repository')
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
if not repo:
|
||||
# Make sure the repo actually exists.
|
||||
abort(404, message='Unknown repository', issue='unknown-repo')
|
||||
|
||||
logger.debug('GCing repository')
|
||||
model.garbage_collect_repository(namespace, repository)
|
||||
model.repository.garbage_collect_repository(namespace, repository)
|
||||
|
||||
# Generate a job for each notification that has been added to this repo
|
||||
logger.debug('Adding notifications for repository')
|
||||
|
@ -269,10 +258,10 @@ def get_repository_images(namespace, repository):
|
|||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
|
||||
# TODO invalidate token?
|
||||
if permission.can() or model.repository_is_public(namespace, repository):
|
||||
if permission.can() or model.repository.repository_is_public(namespace, repository):
|
||||
# We can't rely on permissions to tell us if a repo exists anymore
|
||||
logger.debug('Looking up repository')
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
if not repo:
|
||||
abort(404, message='Unknown repository', issue='unknown-repo')
|
||||
|
||||
|
@ -320,7 +309,7 @@ def get_search():
|
|||
username = user.username
|
||||
|
||||
if query:
|
||||
matching = model.get_matching_repositories(query, username)
|
||||
matching = model.repository.get_matching_repositories(query, username)
|
||||
else:
|
||||
matching = []
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import logging
|
||||
import json
|
||||
|
||||
from flask import (make_response, request, session, Response, redirect,
|
||||
Blueprint, abort as flask_abort)
|
||||
from flask import make_response, request, session, Response, redirect, abort as flask_abort
|
||||
from functools import wraps
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
|
@ -61,7 +60,7 @@ def require_completion(f):
|
|||
@wraps(f)
|
||||
def wrapper(namespace, repository, *args, **kwargs):
|
||||
image_id = kwargs['image_id']
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if image_is_uploading(repo_image):
|
||||
abort(400, 'Image %(image_id)s is being uploaded, retry later',
|
||||
issue='upload-in-progress', image_id=kwargs['image_id'])
|
||||
|
@ -104,9 +103,9 @@ def head_image_layer(namespace, repository, image_id, headers):
|
|||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
|
||||
logger.debug('Checking repo permissions')
|
||||
if permission.can() or model.repository_is_public(namespace, repository):
|
||||
if permission.can() or model.repository.repository_is_public(namespace, repository):
|
||||
logger.debug('Looking up repo image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if not repo_image:
|
||||
logger.debug('Image not found')
|
||||
abort(404, 'Image %(image_id)s not found', issue='unknown-image',
|
||||
|
@ -138,9 +137,9 @@ def get_image_layer(namespace, repository, image_id, headers):
|
|||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
|
||||
logger.debug('Checking repo permissions')
|
||||
if permission.can() or model.repository_is_public(namespace, repository):
|
||||
if permission.can() or model.repository.repository_is_public(namespace, repository):
|
||||
logger.debug('Looking up repo image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if not repo_image:
|
||||
logger.debug('Image not found')
|
||||
abort(404, 'Image %(image_id)s not found', issue='unknown-image',
|
||||
|
@ -183,7 +182,7 @@ def put_image_layer(namespace, repository, image_id):
|
|||
abort(403)
|
||||
|
||||
logger.debug('Retrieving image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
try:
|
||||
logger.debug('Retrieving image data')
|
||||
uuid = repo_image.storage.uuid
|
||||
|
@ -236,17 +235,16 @@ def put_image_layer(namespace, repository, image_id):
|
|||
|
||||
try:
|
||||
# Save the size of the image.
|
||||
model.set_image_size(image_id, namespace, repository, size_info.compressed_size,
|
||||
size_info.uncompressed_size)
|
||||
model.image.set_image_size(image_id, namespace, repository, size_info.compressed_size,
|
||||
size_info.uncompressed_size)
|
||||
|
||||
if requires_tarsum:
|
||||
tmp.seek(0)
|
||||
csums.append(checksums.compute_tarsum(tmp, json_data))
|
||||
tmp.close()
|
||||
|
||||
except (IOError, checksums.TarError) as e:
|
||||
logger.debug('put_image_layer: Error when computing tarsum '
|
||||
'{0}'.format(e))
|
||||
except (IOError, checksums.TarError) as exc:
|
||||
logger.debug('put_image_layer: Error when computing tarsum %s', exc)
|
||||
|
||||
if repo_image.storage.checksum is None:
|
||||
# We don't have a checksum stored yet, that's fine skipping the check.
|
||||
|
@ -268,7 +266,7 @@ def put_image_layer(namespace, repository, image_id):
|
|||
# The layer is ready for download, send a job to the work queue to
|
||||
# process it.
|
||||
logger.debug('Adding layer to diff queue')
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({
|
||||
'namespace_user_id': repo.namespace_user.id,
|
||||
'repository': repository,
|
||||
|
@ -310,7 +308,7 @@ def put_image_checksum(namespace, repository, image_id):
|
|||
issue='missing-checksum-cookie', image_id=image_id)
|
||||
|
||||
logger.debug('Looking up repo image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if not repo_image or not repo_image.storage:
|
||||
abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id)
|
||||
|
||||
|
@ -331,8 +329,8 @@ def put_image_checksum(namespace, repository, image_id):
|
|||
abort(400, err)
|
||||
|
||||
if checksum not in session.get('checksum', []):
|
||||
logger.debug('session checksums: %s' % session.get('checksum', []))
|
||||
logger.debug('client supplied checksum: %s' % checksum)
|
||||
logger.debug('session checksums: %s', session.get('checksum', []))
|
||||
logger.debug('client supplied checksum: %s', checksum)
|
||||
logger.debug('put_image_checksum: Wrong checksum')
|
||||
abort(400, 'Checksum mismatch for image: %(image_id)s',
|
||||
issue='checksum-mismatch', image_id=image_id)
|
||||
|
@ -343,7 +341,7 @@ def put_image_checksum(namespace, repository, image_id):
|
|||
# The layer is ready for download, send a job to the work queue to
|
||||
# process it.
|
||||
logger.debug('Adding layer to diff queue')
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
image_diff_queue.put([repo.namespace_user.username, repository, image_id], json.dumps({
|
||||
'namespace_user_id': repo.namespace_user.id,
|
||||
'repository': repository,
|
||||
|
@ -362,12 +360,11 @@ def put_image_checksum(namespace, repository, image_id):
|
|||
def get_image_json(namespace, repository, image_id, headers):
|
||||
logger.debug('Checking repo permissions')
|
||||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
if not permission.can() and not model.repository_is_public(namespace,
|
||||
repository):
|
||||
if not permission.can() and not model.repository.repository_is_public(namespace, repository):
|
||||
abort(403)
|
||||
|
||||
logger.debug('Looking up repo image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
|
||||
logger.debug('Looking up repo layer data')
|
||||
try:
|
||||
|
@ -394,12 +391,11 @@ def get_image_json(namespace, repository, image_id, headers):
|
|||
def get_image_ancestry(namespace, repository, image_id, headers):
|
||||
logger.debug('Checking repo permissions')
|
||||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
if not permission.can() and not model.repository_is_public(namespace,
|
||||
repository):
|
||||
if not permission.can() and not model.repository.repository_is_public(namespace, repository):
|
||||
abort(403)
|
||||
|
||||
logger.debug('Looking up repo image')
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
|
||||
logger.debug('Looking up image data')
|
||||
try:
|
||||
|
@ -465,22 +461,23 @@ def put_image_json(namespace, repository, image_id):
|
|||
|
||||
logger.debug('Looking up repo image')
|
||||
|
||||
repo = model.get_repository(namespace, repository)
|
||||
repo = model.repository.get_repository(namespace, repository)
|
||||
if repo is None:
|
||||
abort(404, 'Repository does not exist: %(namespace)s/%(repository)s', issue='no-repo',
|
||||
namespace=namespace, repository=repository)
|
||||
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if not repo_image:
|
||||
username = (get_authenticated_user() and get_authenticated_user().username or
|
||||
get_grant_user_context())
|
||||
logger.debug('Image not found, creating image with initiating user context: %s', username)
|
||||
repo_image = model.find_create_or_link_image(image_id, repo, username, {},
|
||||
store.preferred_locations[0])
|
||||
repo_image = model.image.find_create_or_link_image(image_id, repo, username, {},
|
||||
store.preferred_locations[0])
|
||||
|
||||
# Create a temporary tag to prevent this image from getting garbage collected while the push
|
||||
# is in progress.
|
||||
model.create_temporary_hidden_tag(repo, repo_image, app.config['PUSH_TEMP_TAG_EXPIRATION_SEC'])
|
||||
model.tag.create_temporary_hidden_tag(repo, repo_image,
|
||||
app.config['PUSH_TEMP_TAG_EXPIRATION_SEC'])
|
||||
|
||||
uuid = repo_image.storage.uuid
|
||||
|
||||
|
@ -493,7 +490,7 @@ def put_image_json(namespace, repository, image_id):
|
|||
parent_image = None
|
||||
if parent_id:
|
||||
logger.debug('Looking up parent image')
|
||||
parent_image = model.get_repo_image_extended(namespace, repository, parent_id)
|
||||
parent_image = model.image.get_repo_image_extended(namespace, repository, parent_id)
|
||||
|
||||
parent_uuid = parent_image and parent_image.storage.uuid
|
||||
parent_locations = parent_image and parent_image.storage.locations
|
||||
|
@ -523,9 +520,8 @@ def put_image_json(namespace, repository, image_id):
|
|||
command = json.dumps(command_list) if command_list else None
|
||||
|
||||
logger.debug('Setting image metadata')
|
||||
model.set_image_metadata(image_id, namespace, repository,
|
||||
data.get('created'), data.get('comment'), command,
|
||||
parent_image)
|
||||
model.image.set_image_metadata(image_id, namespace, repository, data.get('created'),
|
||||
data.get('comment'), command, parent_image)
|
||||
|
||||
logger.debug('Putting json path')
|
||||
store.put_content(repo_image.storage.locations, json_path, request.data)
|
||||
|
@ -536,7 +532,7 @@ def put_image_json(namespace, repository, image_id):
|
|||
generate_ancestry(image_id, uuid, repo_image.storage.locations, parent_id, parent_uuid,
|
||||
parent_locations)
|
||||
except IOError as ioe:
|
||||
logger.debug('Error when generating ancestry: %s' % ioe.message)
|
||||
logger.debug('Error when generating ancestry: %s', ioe.message)
|
||||
abort(404)
|
||||
|
||||
logger.debug('Done')
|
||||
|
@ -544,9 +540,9 @@ def put_image_json(namespace, repository, image_id):
|
|||
|
||||
|
||||
def process_image_changes(namespace, repository, image_id):
|
||||
logger.debug('Generating diffs for image: %s' % image_id)
|
||||
logger.debug('Generating diffs for image: %s', image_id)
|
||||
|
||||
repo_image = model.get_repo_image_extended(namespace, repository, image_id)
|
||||
repo_image = model.image.get_repo_image_extended(namespace, repository, image_id)
|
||||
if not repo_image:
|
||||
logger.warning('No image for id: %s', image_id)
|
||||
return None, None
|
||||
|
@ -557,11 +553,11 @@ def process_image_changes(namespace, repository, image_id):
|
|||
image_trie_path = store.image_file_trie_path(uuid)
|
||||
|
||||
if store.exists(repo_image.storage.locations, image_diffs_path):
|
||||
logger.debug('Diffs already exist for image: %s' % image_id)
|
||||
logger.debug('Diffs already exist for image: %s', image_id)
|
||||
return image_trie_path, repo_image.storage.locations
|
||||
|
||||
image = model.get_image_by_id(namespace, repository, image_id)
|
||||
parents = model.get_parent_images(namespace, repository, image)
|
||||
image = model.image.get_image_by_id(namespace, repository, image_id)
|
||||
parents = model.image.get_parent_images(namespace, repository, image)
|
||||
|
||||
# Compute the diffs and fs for the parent first if necessary
|
||||
parent_trie_path = None
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import logging
|
||||
import json
|
||||
|
||||
from flask import abort, request, jsonify, make_response, Blueprint, session
|
||||
from flask import abort, request, jsonify, make_response, session
|
||||
|
||||
from app import app
|
||||
from util.names import parse_repository_name
|
||||
|
@ -17,32 +17,30 @@ from endpoints.v1 import v1_bp
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@v1_bp.route('/repositories/<path:repository>/tags',
|
||||
methods=['GET'])
|
||||
@v1_bp.route('/repositories/<path:repository>/tags', methods=['GET'])
|
||||
@process_auth
|
||||
@anon_protect
|
||||
@parse_repository_name
|
||||
def get_tags(namespace, repository):
|
||||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
|
||||
if permission.can() or model.repository_is_public(namespace, repository):
|
||||
tags = model.list_repository_tags(namespace, repository)
|
||||
if permission.can() or model.repository.repository_is_public(namespace, repository):
|
||||
tags = model.tag.list_repository_tags(namespace, repository)
|
||||
tag_map = {tag.name: tag.image.docker_image_id for tag in tags}
|
||||
return jsonify(tag_map)
|
||||
|
||||
abort(403)
|
||||
|
||||
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>',
|
||||
methods=['GET'])
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>', methods=['GET'])
|
||||
@process_auth
|
||||
@anon_protect
|
||||
@parse_repository_name
|
||||
def get_tag(namespace, repository, tag):
|
||||
permission = ReadRepositoryPermission(namespace, repository)
|
||||
|
||||
if permission.can() or model.repository_is_public(namespace, repository):
|
||||
tag_image = model.get_tag_image(namespace, repository, tag)
|
||||
if permission.can() or model.repository.repository_is_public(namespace, repository):
|
||||
tag_image = model.tag.get_tag_image(namespace, repository, tag)
|
||||
resp = make_response('"%s"' % tag_image.docker_image_id)
|
||||
resp.headers['Content-Type'] = 'application/json'
|
||||
return resp
|
||||
|
@ -50,8 +48,7 @@ def get_tag(namespace, repository, tag):
|
|||
abort(403)
|
||||
|
||||
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>',
|
||||
methods=['PUT'])
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>', methods=['PUT'])
|
||||
@process_auth
|
||||
@anon_protect
|
||||
@parse_repository_name
|
||||
|
@ -60,7 +57,7 @@ def put_tag(namespace, repository, tag):
|
|||
|
||||
if permission.can():
|
||||
docker_image_id = json.loads(request.data)
|
||||
model.create_or_update_tag(namespace, repository, tag, docker_image_id)
|
||||
model.tag.create_or_update_tag(namespace, repository, tag, docker_image_id)
|
||||
|
||||
# Store the updated tag.
|
||||
if not 'pushed_tags' in session:
|
||||
|
@ -73,8 +70,7 @@ def put_tag(namespace, repository, tag):
|
|||
abort(403)
|
||||
|
||||
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>',
|
||||
methods=['DELETE'])
|
||||
@v1_bp.route('/repositories/<path:repository>/tags/<tag>', methods=['DELETE'])
|
||||
@process_auth
|
||||
@anon_protect
|
||||
@parse_repository_name
|
||||
|
@ -82,8 +78,8 @@ def delete_tag(namespace, repository, tag):
|
|||
permission = ModifyRepositoryPermission(namespace, repository)
|
||||
|
||||
if permission.can():
|
||||
model.delete_tag(namespace, repository, tag)
|
||||
model.garbage_collect_repository(namespace, repository)
|
||||
model.tag.delete_tag(namespace, repository, tag)
|
||||
model.repository.garbage_collect_repository(namespace, repository)
|
||||
|
||||
return make_response('Deleted', 200)
|
||||
|
Reference in a new issue