Merge branch 'orgs' of https://bitbucket.org/yackob03/quay into orgs
This commit is contained in:
commit
5858ba0ee0
18 changed files with 658 additions and 661 deletions
10
app.py
10
app.py
|
@ -7,7 +7,8 @@ from flask.ext.principal import Principal
|
|||
from flask.ext.login import LoginManager
|
||||
from flask.ext.mail import Mail
|
||||
|
||||
from config import ProductionConfig, DebugConfig, LocalHostedConfig
|
||||
from config import (ProductionConfig, DebugConfig, LocalHostedConfig,
|
||||
TestConfig)
|
||||
from util import analytics
|
||||
|
||||
|
||||
|
@ -22,6 +23,9 @@ if stack.startswith('prod'):
|
|||
elif stack.startswith('localhosted'):
|
||||
logger.info('Running with debug config on production data.')
|
||||
config = LocalHostedConfig()
|
||||
elif stack.startswith('test'):
|
||||
logger.info('Running with test config on ephemeral data.')
|
||||
config = TestConfig()
|
||||
else:
|
||||
logger.info('Running with debug config.')
|
||||
config = DebugConfig()
|
||||
|
@ -36,6 +40,6 @@ login_manager.init_app(app)
|
|||
mail = Mail()
|
||||
mail.init_app(app)
|
||||
|
||||
stripe.api_key = app.config['STRIPE_SECRET_KEY']
|
||||
stripe.api_key = app.config.get('STRIPE_SECRET_KEY', None)
|
||||
|
||||
mixpanel = analytics.init_app(app)
|
||||
mixpanel = app.config['ANALYTICS'].init_app(app)
|
||||
|
|
|
@ -65,7 +65,8 @@ class ModifyRepositoryPermission(Permission):
|
|||
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
||||
write_need = _RepositoryNeed(namespace, name, 'write')
|
||||
org_admin_need = _OrganizationNeed(namespace, 'admin')
|
||||
super(ModifyRepositoryPermission, self).__init__(admin_need, write_need)
|
||||
super(ModifyRepositoryPermission, self).__init__(admin_need, write_need,
|
||||
org_admin_need)
|
||||
|
||||
|
||||
class ReadRepositoryPermission(Permission):
|
||||
|
|
59
config.py
59
config.py
|
@ -2,6 +2,13 @@ import logging
|
|||
import sys
|
||||
|
||||
from peewee import MySQLDatabase, SqliteDatabase
|
||||
from storage.s3 import S3Storage
|
||||
from storage.local import LocalStorage
|
||||
from data.userfiles import UserRequestFiles
|
||||
from util import analytics
|
||||
|
||||
from test.teststorage import FakeStorage, FakeUserfiles
|
||||
from test import analytics as fake_analytics
|
||||
|
||||
|
||||
LOG_FORMAT = '%(asctime)-15s - %(levelname)s - %(pathname)s - ' + \
|
||||
|
@ -31,6 +38,12 @@ class SQLiteDB(object):
|
|||
DB_DRIVER = SqliteDatabase
|
||||
|
||||
|
||||
class EphemeralDB(object):
|
||||
DB_NAME = ':memory:'
|
||||
DB_CONNECTION_ARGS = {}
|
||||
DB_DRIVER = SqliteDatabase
|
||||
|
||||
|
||||
class RDSMySQL(object):
|
||||
DB_NAME = 'quay'
|
||||
DB_CONNECTION_ARGS = {
|
||||
|
@ -49,12 +62,27 @@ class AWSCredentials(object):
|
|||
|
||||
|
||||
class S3Storage(AWSCredentials):
|
||||
STORAGE_KIND = 's3'
|
||||
STORAGE = S3Storage('', AWSCredentials.AWS_ACCESS_KEY,
|
||||
AWSCredentials.AWS_SECRET_KEY,
|
||||
AWSCredentials.REGISTRY_S3_BUCKET)
|
||||
|
||||
|
||||
class LocalStorage(object):
|
||||
STORAGE_KIND = 'local'
|
||||
LOCAL_STORAGE_DIR = 'test/data/registry'
|
||||
STORAGE = LocalStorage('test/data/registry')
|
||||
|
||||
|
||||
class FakeStorage(object):
|
||||
STORAGE = FakeStorage()
|
||||
|
||||
|
||||
class FakeUserfiles(object):
|
||||
USERFILES = FakeUserfiles()
|
||||
|
||||
|
||||
class S3Userfiles(AWSCredentials):
|
||||
USERFILES = UserRequestFiles(AWSCredentials.AWS_ACCESS_KEY,
|
||||
AWSCredentials.AWS_SECRET_KEY,
|
||||
AWSCredentials.REGISTRY_S3_BUCKET)
|
||||
|
||||
|
||||
class StripeTestConfig(object):
|
||||
|
@ -67,11 +95,16 @@ class StripeLiveConfig(object):
|
|||
STRIPE_PUBLISHABLE_KEY = 'pk_live_P5wLU0vGdHnZGyKnXlFG4oiu'
|
||||
|
||||
|
||||
class FakeAnalytics(object):
|
||||
ANALYTICS = fake_analytics
|
||||
|
||||
|
||||
class MixpanelTestConfig(object):
|
||||
ANALYTICS = analytics
|
||||
MIXPANEL_KEY = '38014a0f27e7bdc3ff8cc7cc29c869f9'
|
||||
|
||||
|
||||
class MixpanelProdConfig(object):
|
||||
class MixpanelProdConfig(MixpanelTestConfig):
|
||||
MIXPANEL_KEY = '50ff2b2569faa3a51c8f5724922ffb7e'
|
||||
|
||||
|
||||
|
@ -100,9 +133,20 @@ class BuildNodeConfig(object):
|
|||
BUILD_NODE_PULL_TOKEN = 'F02O2E86CQLKZUQ0O81J8XDHQ6F0N1V36L9JTOEEK6GKKMT1GI8PTJQT4OU88Y6G'
|
||||
|
||||
|
||||
class TestConfig(FlaskConfig, FakeStorage, EphemeralDB, FakeUserfiles,
|
||||
FakeAnalytics):
|
||||
LOGGING_CONFIG = {
|
||||
'level': logging.DEBUG,
|
||||
'format': LOG_FORMAT
|
||||
}
|
||||
POPULATE_DB_TEST_DATA = True
|
||||
TESTING = True
|
||||
INCLUDE_TEST_ENDPOINTS = True
|
||||
|
||||
|
||||
class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB,
|
||||
StripeTestConfig, MixpanelTestConfig, GitHubTestConfig,
|
||||
DigitalOceanConfig, AWSCredentials, BuildNodeConfig):
|
||||
DigitalOceanConfig, BuildNodeConfig, S3Userfiles):
|
||||
LOGGING_CONFIG = {
|
||||
'level': logging.DEBUG,
|
||||
'format': LOG_FORMAT
|
||||
|
@ -115,7 +159,7 @@ class DebugConfig(FlaskConfig, MailConfig, LocalStorage, SQLiteDB,
|
|||
class LocalHostedConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL,
|
||||
StripeLiveConfig, MixpanelTestConfig,
|
||||
GitHubProdConfig, DigitalOceanConfig,
|
||||
BuildNodeConfig):
|
||||
BuildNodeConfig, S3Userfiles):
|
||||
LOGGING_CONFIG = {
|
||||
'level': logging.DEBUG,
|
||||
'format': LOG_FORMAT
|
||||
|
@ -125,7 +169,8 @@ class LocalHostedConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL,
|
|||
|
||||
class ProductionConfig(FlaskConfig, MailConfig, S3Storage, RDSMySQL,
|
||||
StripeLiveConfig, MixpanelProdConfig,
|
||||
GitHubProdConfig, DigitalOceanConfig, BuildNodeConfig):
|
||||
GitHubProdConfig, DigitalOceanConfig, BuildNodeConfig,
|
||||
S3Userfiles):
|
||||
LOGGING_CONFIG = {
|
||||
'stream': sys.stderr,
|
||||
'level': logging.DEBUG,
|
||||
|
|
|
@ -149,7 +149,11 @@ def remove_team(org_name, team_name, removed_by_username):
|
|||
|
||||
|
||||
def add_user_to_team(user, team):
|
||||
return TeamMember.create(user=user, team=team)
|
||||
try:
|
||||
return TeamMember.create(user=user, team=team)
|
||||
except Exception:
|
||||
raise DataModelException('Unable to add user \'%s\' to team: \'%s\'' %
|
||||
(user.username, team.name))
|
||||
|
||||
|
||||
def remove_user_from_team(org_name, team_name, username, removed_by_username):
|
||||
|
@ -164,7 +168,7 @@ def remove_user_from_team(org_name, team_name, username, removed_by_username):
|
|||
|
||||
if not found:
|
||||
raise DataModelException('User %s does not belong to team %s' %
|
||||
(username, teamname))
|
||||
(username, team_name))
|
||||
|
||||
if username == removed_by_username:
|
||||
admin_team_query = __get_user_admin_teams(org_name, team_name, username)
|
||||
|
@ -722,15 +726,13 @@ def delete_team_permission(team_name, namespace_name, repository_name):
|
|||
fetched[0].delete_instance()
|
||||
|
||||
|
||||
def __set_entity_repo_permission(entity_id, entity_table, entity_id_property,
|
||||
permission_entity_property, namespace_name,
|
||||
repository_name, role_name):
|
||||
entity = entity_table.get(entity_id_property == entity_id)
|
||||
def __set_entity_repo_permission(entity, permission_entity_property,
|
||||
namespace_name, repository_name, role_name):
|
||||
repo = Repository.get(Repository.name == repository_name,
|
||||
Repository.namespace == namespace_name)
|
||||
new_role = Role.get(Role.name == role_name)
|
||||
|
||||
# Fetch any existing permission for this user on the repo
|
||||
# Fetch any existing permission for this entity on the repo
|
||||
try:
|
||||
entity_attr = getattr(RepositoryPermission, permission_entity_property)
|
||||
perm = RepositoryPermission.get(entity_attr == entity,
|
||||
|
@ -750,16 +752,21 @@ def set_user_repo_permission(username, namespace_name, repository_name,
|
|||
if username == namespace_name:
|
||||
raise DataModelException('Namespace owner must always be admin.')
|
||||
|
||||
return __set_entity_repo_permission(username, User, User.username, 'user',
|
||||
namespace_name, repository_name,
|
||||
role_name)
|
||||
user = User.get(User.username == username)
|
||||
return __set_entity_repo_permission(user, 'user', namespace_name,
|
||||
repository_name, role_name)
|
||||
|
||||
|
||||
def set_team_repo_permission(team_name, namespace_name, repository_name,
|
||||
role_name):
|
||||
return __set_entity_repo_permission(team_name, Team, Team.name, 'team',
|
||||
namespace_name, repository_name,
|
||||
role_name)
|
||||
team = list(Team.select().join(User).where(Team.name == team_name,
|
||||
User.username == namespace_name))
|
||||
if not team:
|
||||
raise DataModelException('No team \'%s\' in organization \'%s\'.' %
|
||||
(team_name, namespace_name))
|
||||
|
||||
return __set_entity_repo_permission(team[0], 'team', namespace_name,
|
||||
repository_name, role_name)
|
||||
|
||||
|
||||
def purge_repository(namespace_name, repository_name):
|
||||
|
|
|
@ -11,10 +11,7 @@ from flask.ext.principal import identity_changed, AnonymousIdentity
|
|||
from functools import wraps
|
||||
from collections import defaultdict
|
||||
|
||||
import storage
|
||||
|
||||
from data import model
|
||||
from data.userfiles import UserRequestFiles
|
||||
from data.queue import dockerfile_build_queue
|
||||
from data.plans import USER_PLANS, BUSINESS_PLANS, get_plan
|
||||
from app import app
|
||||
|
@ -33,7 +30,8 @@ from endpoints.web import common_login
|
|||
from util.cache import cache_control
|
||||
|
||||
|
||||
store = storage.load()
|
||||
store = app.config['STORAGE']
|
||||
user_files = app.config['USERFILES']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -46,24 +44,16 @@ def api_login_required(f):
|
|||
return decorated_view
|
||||
|
||||
|
||||
def required_json_args(*required_args):
|
||||
def wrap(f):
|
||||
@wraps(f)
|
||||
def wrapped(*args, **kwargs):
|
||||
request_data = request.get_json()
|
||||
for arg in required_args:
|
||||
if arg not in request_data:
|
||||
abort(400)
|
||||
return f(*args, **kwargs)
|
||||
return wrapped
|
||||
return wrap
|
||||
|
||||
|
||||
@app.errorhandler(model.DataModelException)
|
||||
def handle_dme(ex):
|
||||
return make_response(ex.message, 400)
|
||||
|
||||
|
||||
@app.errorhandler(KeyError)
|
||||
def handle_dme(ex):
|
||||
return make_response(ex.message, 400)
|
||||
|
||||
|
||||
@app.route('/api/')
|
||||
def welcome():
|
||||
return make_response('welcome', 200)
|
||||
|
@ -135,7 +125,6 @@ def change_user_details():
|
|||
|
||||
|
||||
@app.route('/api/user/', methods=['POST'])
|
||||
@required_json_args('username', 'password', 'email')
|
||||
def create_user_api():
|
||||
user_data = request.get_json()
|
||||
|
||||
|
@ -162,7 +151,6 @@ def create_user_api():
|
|||
|
||||
|
||||
@app.route('/api/signin', methods=['POST'])
|
||||
@required_json_args('username', 'password')
|
||||
def signin_api():
|
||||
signin_data = request.get_json()
|
||||
|
||||
|
@ -202,7 +190,6 @@ def logout():
|
|||
|
||||
|
||||
@app.route("/api/recovery", methods=['POST'])
|
||||
@required_json_args('email')
|
||||
def send_recovery():
|
||||
email = request.get_json()['email']
|
||||
code = model.create_reset_password_email_code(email)
|
||||
|
@ -265,11 +252,6 @@ def get_matching_entities(prefix):
|
|||
})
|
||||
|
||||
|
||||
user_files = UserRequestFiles(app.config['AWS_ACCESS_KEY'],
|
||||
app.config['AWS_SECRET_KEY'],
|
||||
app.config['REGISTRY_S3_BUCKET'])
|
||||
|
||||
|
||||
def team_view(orgname, t):
|
||||
view_permission = ViewTeamPermission(orgname, t.name)
|
||||
role = model.get_team_org_role(t).name
|
||||
|
@ -526,7 +508,7 @@ def create_repo_api():
|
|||
if existing:
|
||||
return make_response('Repository already exists', 400)
|
||||
|
||||
visibility = request.get_json()['visibility']
|
||||
visibility = json['visibility']
|
||||
|
||||
repo = model.create_repository(namespace_name, repository_name, owner,
|
||||
visibility)
|
||||
|
@ -621,7 +603,7 @@ def update_repo_api(namespace, repository):
|
|||
'success': True
|
||||
})
|
||||
|
||||
abort(404)
|
||||
abort(403)
|
||||
|
||||
|
||||
@app.route('/api/repository/<path:repository>/changevisibility',
|
||||
|
@ -750,7 +732,6 @@ def get_repo_builds(namespace, repository):
|
|||
|
||||
@app.route('/api/filedrop/', methods=['POST'])
|
||||
@api_login_required
|
||||
@required_json_args('mimeType')
|
||||
def get_filedrop_url():
|
||||
mime_type = request.get_json()['mimeType']
|
||||
(url, file_id) = user_files.prepare_for_drop(mime_type)
|
||||
|
@ -778,9 +759,11 @@ def request_repo_build(namespace, repository):
|
|||
tag)
|
||||
dockerfile_build_queue.put(json.dumps({'build_id': build_request.id}))
|
||||
|
||||
return jsonify({
|
||||
resp = jsonify({
|
||||
'started': True
|
||||
})
|
||||
resp.status_code = 201
|
||||
return resp
|
||||
|
||||
abort(403) # Permissions denied
|
||||
|
||||
|
@ -961,7 +944,7 @@ def get_team_permissions(namespace, repository, teamname):
|
|||
(namespace, repository, teamname))
|
||||
permission = AdministerRepositoryPermission(namespace, repository)
|
||||
if permission.can():
|
||||
perm = model.get_team_reponame_permission(username, namespace, repository)
|
||||
perm = model.get_team_reponame_permission(teamname, namespace, repository)
|
||||
return jsonify(role_view(perm))
|
||||
|
||||
abort(403) # Permission denied
|
||||
|
@ -979,13 +962,8 @@ def change_user_permissions(namespace, repository, username):
|
|||
logger.debug('Setting permission to: %s for user %s' %
|
||||
(new_permission['role'], username))
|
||||
|
||||
try:
|
||||
perm = model.set_user_repo_permission(username, namespace, repository,
|
||||
new_permission['role'])
|
||||
except model.DataModelException:
|
||||
logger.warning('User tried to remove themselves as admin.')
|
||||
abort(409)
|
||||
|
||||
perm = model.set_user_repo_permission(username, namespace, repository,
|
||||
new_permission['role'])
|
||||
perm_view = role_view(perm)
|
||||
|
||||
try:
|
||||
|
@ -1017,12 +995,8 @@ def change_team_permissions(namespace, repository, teamname):
|
|||
logger.debug('Setting permission to: %s for team %s' %
|
||||
(new_permission['role'], teamname))
|
||||
|
||||
try:
|
||||
perm = model.set_team_repo_permission(teamname, namespace, repository,
|
||||
new_permission['role'])
|
||||
except model.DataModelException:
|
||||
logger.warning('User tried to remove themselves as admin.')
|
||||
abort(409)
|
||||
perm = model.set_team_repo_permission(teamname, namespace, repository,
|
||||
new_permission['role'])
|
||||
|
||||
resp = jsonify(role_view(perm))
|
||||
if request.method == 'POST':
|
||||
|
@ -1039,12 +1013,7 @@ def change_team_permissions(namespace, repository, teamname):
|
|||
def delete_user_permissions(namespace, repository, username):
|
||||
permission = AdministerRepositoryPermission(namespace, repository)
|
||||
if permission.can():
|
||||
try:
|
||||
model.delete_user_permission(username, namespace, repository)
|
||||
except model.DataModelException:
|
||||
logger.warning('User tried to remove themselves as admin.')
|
||||
abort(409)
|
||||
|
||||
model.delete_user_permission(username, namespace, repository)
|
||||
return make_response('Deleted', 204)
|
||||
|
||||
abort(403) # Permission denied
|
||||
|
@ -1057,12 +1026,7 @@ def delete_user_permissions(namespace, repository, username):
|
|||
def delete_team_permissions(namespace, repository, teamname):
|
||||
permission = AdministerRepositoryPermission(namespace, repository)
|
||||
if permission.can():
|
||||
try:
|
||||
model.delete_team_permission(teamname, namespace, repository)
|
||||
except model.DataModelException:
|
||||
logger.warning('User tried to remove themselves as admin.')
|
||||
abort(409)
|
||||
|
||||
model.delete_team_permission(teamname, namespace, repository)
|
||||
return make_response('Deleted', 204)
|
||||
|
||||
abort(403) # Permission denied
|
||||
|
|
|
@ -6,7 +6,6 @@ from functools import wraps
|
|||
from datetime import datetime
|
||||
from time import time
|
||||
|
||||
import storage
|
||||
from data.queue import image_diff_queue
|
||||
|
||||
from app import app
|
||||
|
@ -17,7 +16,7 @@ from auth.permissions import (ReadRepositoryPermission,
|
|||
from data import model
|
||||
|
||||
|
||||
store = storage.load()
|
||||
store = app.config['STORAGE']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ import json
|
|||
|
||||
from flask import abort, request, jsonify, make_response
|
||||
|
||||
import storage
|
||||
|
||||
from app import app
|
||||
from util.names import parse_repository_name
|
||||
from auth.auth import process_auth
|
||||
|
@ -14,7 +12,6 @@ from auth.permissions import (ReadRepositoryPermission,
|
|||
from data import model
|
||||
|
||||
|
||||
store = storage.load()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
12
initdb.py
12
initdb.py
|
@ -8,15 +8,13 @@ from datetime import datetime, timedelta
|
|||
from flask import url_for
|
||||
from peewee import SqliteDatabase, create_model_tables, drop_model_tables
|
||||
|
||||
import storage
|
||||
|
||||
from data.database import *
|
||||
from data import model
|
||||
from app import app
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
store = storage.load()
|
||||
store = app.config['STORAGE']
|
||||
|
||||
SAMPLE_DIFFS = ['test/data/sample/diffs/diffs%s.json' % i
|
||||
for i in range(1, 10)]
|
||||
|
@ -141,6 +139,10 @@ def populate_database():
|
|||
new_user_3.verified = True
|
||||
new_user_3.save()
|
||||
|
||||
reader = model.create_user('reader', 'password', 'no1@thanks.com')
|
||||
reader.verified = True
|
||||
reader.save()
|
||||
|
||||
__generate_repository(new_user_1, 'simple', 'Simple repository.', False,
|
||||
[], (4, [], ['latest', 'prod']))
|
||||
|
||||
|
@ -168,7 +170,8 @@ def populate_database():
|
|||
|
||||
__generate_repository(new_user_1, 'shared',
|
||||
'Shared repository, another user can write.', False,
|
||||
[(new_user_2, 'write')], (5, [], 'latest'))
|
||||
[(new_user_2, 'write'), (reader, 'read')],
|
||||
(5, [], 'latest'))
|
||||
|
||||
building = __generate_repository(new_user_1, 'building',
|
||||
'Empty repository which is building.',
|
||||
|
@ -186,6 +189,7 @@ def populate_database():
|
|||
model.set_team_repo_permission(reader_team.name, org_repo.namespace,
|
||||
org_repo.name, 'read')
|
||||
model.add_user_to_team(new_user_2, reader_team)
|
||||
model.add_user_to_team(reader, reader_team)
|
||||
|
||||
token = model.create_access_token(building, 'write')
|
||||
tag = 'ci.devtable.com:5000/%s/%s' % (building.namespace, building.name)
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
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>
|
||||
"""
|
||||
|
||||
# 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)
|
||||
|
||||
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_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_ancestry_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def repository_namespace_path(self, namespace, repository):
|
||||
return '{0}/{1}/{2}/'.format(self.images, namespace, repository)
|
||||
|
||||
def image_file_trie_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/files.trie'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def image_file_diffs_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/diffs.json'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def get_content(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def put_content(self, path, content):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_read(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_read_file(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_write(self, path, fp):
|
||||
raise NotImplementedError
|
||||
|
||||
def list_directory(self, path=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def exists(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def remove(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()
|
||||
|
||||
|
||||
def temp_store_handler():
|
||||
tmpf = tempfile.TemporaryFile()
|
||||
|
||||
def fn(buf):
|
||||
try:
|
||||
tmpf.write(buf)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
return tmpf, fn
|
||||
|
||||
|
||||
from local import LocalStorage
|
||||
from s3 import S3Storage
|
||||
|
||||
|
||||
_storage = {}
|
||||
|
||||
|
||||
def load(kind=None):
|
||||
"""Returns the right storage class according to the configuration."""
|
||||
global _storage
|
||||
|
||||
kind = app.config['STORAGE_KIND']
|
||||
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
|
78
storage/basestorage.py
Normal file
78
storage/basestorage.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
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>
|
||||
"""
|
||||
|
||||
# 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)
|
||||
|
||||
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_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_ancestry_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/ancestry'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def repository_namespace_path(self, namespace, repository):
|
||||
return '{0}/{1}/{2}/'.format(self.images, namespace, repository)
|
||||
|
||||
def image_file_trie_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/files.trie'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def image_file_diffs_path(self, namespace, repository, image_id):
|
||||
return '{0}/{1}/{2}/{3}/diffs.json'.format(self.images, namespace,
|
||||
repository, image_id)
|
||||
|
||||
def get_content(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def put_content(self, path, content):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_read(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_read_file(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def stream_write(self, path, fp):
|
||||
raise NotImplementedError
|
||||
|
||||
def list_directory(self, path=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def exists(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def remove(self, path):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_size(self, path):
|
||||
raise NotImplementedError
|
|
@ -2,7 +2,7 @@
|
|||
import os
|
||||
import shutil
|
||||
|
||||
from . import Storage
|
||||
from basestorage import Storage
|
||||
|
||||
|
||||
class LocalStorage(Storage):
|
||||
|
|
|
@ -5,7 +5,7 @@ import logging
|
|||
import boto.s3.connection
|
||||
import boto.s3.key
|
||||
|
||||
from . import Storage
|
||||
from basestorage import Storage
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
6
test/analytics.py
Normal file
6
test/analytics.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
class FakeMixpanel(object):
|
||||
def send(self, endpoint, json_message):
|
||||
pass
|
||||
|
||||
def init_app(app):
|
||||
return FakeMixpanel()
|
Binary file not shown.
756
test/specs.py
756
test/specs.py
|
@ -7,423 +7,379 @@ from uuid import uuid4
|
|||
|
||||
PUBLIC_REPO = 'public/publicrepo'
|
||||
|
||||
PRIVATE_REPO = 'devtable/complex'
|
||||
PRIVATE_REPO = 'devtable/shared'
|
||||
|
||||
ORG = 'devtableorg'
|
||||
ORG_REPO = ORG + '/orgrepo'
|
||||
ORG_OWNERS = 'owners'
|
||||
ORG_READERS = 'readers'
|
||||
ORG_OWNER = 'devtable'
|
||||
ORG_OWNERS = 'owners'
|
||||
ORG_READERS = 'readers'
|
||||
|
||||
FAKE_IMAGE_ID = uuid4()
|
||||
FAKE_TAG_NAME = uuid4()
|
||||
FAKE_USERNAME = uuid4()
|
||||
FAKE_TEAMNAME = uuid4()
|
||||
FAKE_TOKEN = uuid4()
|
||||
FAKE_IMAGE_ID = str(uuid4())
|
||||
FAKE_TAG_NAME = str(uuid4())
|
||||
FAKE_USERNAME = str(uuid4())
|
||||
FAKE_TOKEN = str(uuid4())
|
||||
|
||||
NEW_ORG_REPO_DETAILS = {
|
||||
'repository': str(uuid4()),
|
||||
'visibility': 'private',
|
||||
'description': '',
|
||||
'namespace': ORG,
|
||||
}
|
||||
|
||||
def open_kwargs(method='GET', json_object=None):
|
||||
kwargs = {
|
||||
'method': method,
|
||||
}
|
||||
NEW_USER_DETAILS = {
|
||||
'username': 'bob',
|
||||
'password': 'password',
|
||||
'email': 'jake@devtable.com',
|
||||
}
|
||||
|
||||
if json_object is not None:
|
||||
kwargs['data'] = json.dumps(json_object)
|
||||
kwargs['content_type'] = 'application/json'
|
||||
SEND_RECOVERY_DETAILS = {
|
||||
'email': 'jacob.moshenko@gmail.com',
|
||||
}
|
||||
|
||||
elif method == 'POST' or method == 'PUT':
|
||||
kwargs['data'] = json.dumps({
|
||||
'fake': 'json',
|
||||
'data': 'here',
|
||||
})
|
||||
kwargs['content_type'] = 'application/json'
|
||||
SIGNIN_DETAILS = {
|
||||
'username': 'devtable',
|
||||
'password': 'password',
|
||||
}
|
||||
|
||||
return kwargs
|
||||
FILE_DROP_DETAILS = {
|
||||
'mimeType': 'application/zip',
|
||||
}
|
||||
|
||||
CHANGE_PERMISSION_DETAILS = {
|
||||
'role': 'admin',
|
||||
}
|
||||
|
||||
def build_anon_spec():
|
||||
return OrderedDict([
|
||||
(url_for('welcome'), (200, open_kwargs())),
|
||||
CREATE_BUILD_DETAILS = {
|
||||
'file_id': str(uuid4()),
|
||||
}
|
||||
|
||||
(url_for('plans_list'), (200, open_kwargs())),
|
||||
CHANGE_VISIBILITY_DETAILS = {
|
||||
'visibility': 'public',
|
||||
}
|
||||
|
||||
(url_for('get_logged_in_user'), (200, open_kwargs())),
|
||||
CREATE_TOKEN_DETAILS = {
|
||||
'friendlyName': 'A new token',
|
||||
}
|
||||
|
||||
(url_for('change_user_details'), (401, open_kwargs('PUT'))),
|
||||
UPDATE_REPO_DETAILS = {
|
||||
'description': 'A new description',
|
||||
}
|
||||
|
||||
(url_for('create_user_api'), (400, open_kwargs('POST'))),
|
||||
|
||||
(url_for('signin_api'), (400, open_kwargs('POST'))),
|
||||
class TestSpec(object):
|
||||
def __init__(self, url, anon_code=401, no_access_code=403, read_code=403,
|
||||
admin_code=200):
|
||||
self._url = url
|
||||
self._data = None
|
||||
self._method = 'GET'
|
||||
|
||||
(url_for('send_recovery'), (400, open_kwargs('POST'))),
|
||||
self.anon_code = anon_code
|
||||
self.no_access_code = no_access_code
|
||||
self.read_code = read_code
|
||||
self.admin_code = admin_code
|
||||
|
||||
(url_for('get_matching_users', prefix='dev'), (401, open_kwargs())),
|
||||
|
||||
(url_for('get_matching_entities', prefix='dev'), (401, open_kwargs())),
|
||||
|
||||
(url_for('get_organization', orgname=ORG), (401, open_kwargs())),
|
||||
|
||||
(url_for('get_organization_private_allowed', orgname=ORG),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('update_organization_team', orgname=ORG, teamname=ORG_OWNERS),
|
||||
(401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_organization_team', orgname=ORG, teamname=ORG_OWNERS),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('get_organization_team_members', orgname=ORG,
|
||||
teamname=ORG_OWNERS), (401, open_kwargs())),
|
||||
|
||||
(url_for('update_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
(401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('create_repo_api'), (401, open_kwargs('POST'))),
|
||||
|
||||
(url_for('match_repos_api'), (200, open_kwargs())),
|
||||
|
||||
(url_for('list_repos_api'), (200, open_kwargs())),
|
||||
|
||||
(url_for('update_repo_api', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs('PUT'))),
|
||||
(url_for('update_repo_api', repository=ORG_REPO),
|
||||
(401, open_kwargs('PUT'))),
|
||||
(url_for('update_repo_api', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('change_repo_visibility_api', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('change_repo_visibility_api', repository=ORG_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('change_repo_visibility_api', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
|
||||
(url_for('delete_repository', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_repository', repository=ORG_REPO),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_repository', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('get_repo_api', repository=PUBLIC_REPO),(200, open_kwargs())),
|
||||
(url_for('get_repo_api', repository=ORG_REPO), (403, open_kwargs())),
|
||||
(url_for('get_repo_api', repository=PRIVATE_REPO), (403, open_kwargs())),
|
||||
|
||||
(url_for('get_repo_builds', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('get_repo_builds', repository=ORG_REPO), (401, open_kwargs())),
|
||||
(url_for('get_repo_builds', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('get_filedrop_url'), (401, open_kwargs('POST'))),
|
||||
|
||||
(url_for('request_repo_build', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('request_repo_build', repository=ORG_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('request_repo_build', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
|
||||
(url_for('list_repository_images', repository=PUBLIC_REPO),
|
||||
(200, open_kwargs())),
|
||||
(url_for('list_repository_images', repository=ORG_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repository_images', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('get_image', repository=PUBLIC_REPO, image_id=FAKE_IMAGE_ID),
|
||||
(404, open_kwargs())),
|
||||
(url_for('get_image', repository=ORG_REPO, image_id=FAKE_IMAGE_ID),
|
||||
(403, open_kwargs())),
|
||||
(url_for('get_image', repository=PRIVATE_REPO, image_id=FAKE_IMAGE_ID),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('get_image_changes', repository=PUBLIC_REPO,
|
||||
image_id=FAKE_IMAGE_ID), (404, open_kwargs())),
|
||||
(url_for('get_image_changes', repository=ORG_REPO,
|
||||
image_id=FAKE_IMAGE_ID), (403, open_kwargs())),
|
||||
(url_for('get_image_changes', repository=PRIVATE_REPO,
|
||||
image_id=FAKE_IMAGE_ID), (403, open_kwargs())),
|
||||
|
||||
(url_for('list_tag_images', repository=PUBLIC_REPO, tag=FAKE_TAG_NAME),
|
||||
(404, open_kwargs())),
|
||||
(url_for('list_tag_images', repository=ORG_REPO, tag=FAKE_TAG_NAME),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_tag_images', repository=PRIVATE_REPO, tag=FAKE_TAG_NAME),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('list_repo_team_permissions', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('list_repo_team_permissions', repository=ORG_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('list_repo_team_permissions', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('list_repo_user_permissions', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('list_repo_user_permissions', repository=ORG_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('list_repo_user_permissions', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('get_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs())),
|
||||
(url_for('get_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs())),
|
||||
(url_for('get_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs())),
|
||||
|
||||
(url_for('get_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs())),
|
||||
(url_for('get_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs())),
|
||||
(url_for('get_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs())),
|
||||
|
||||
(url_for('change_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('PUT'))),
|
||||
(url_for('change_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('PUT'))),
|
||||
(url_for('change_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('change_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('PUT'))),
|
||||
(url_for('change_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('PUT'))),
|
||||
(url_for('change_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('delete_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('list_repo_tokens', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs())),
|
||||
(url_for('list_repo_tokens', repository=ORG_REPO), (401, open_kwargs())),
|
||||
(url_for('list_repo_tokens', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('get_tokens', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs())),
|
||||
(url_for('get_tokens', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs())),
|
||||
(url_for('get_tokens', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs())),
|
||||
|
||||
(url_for('create_token', repository=PUBLIC_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('create_token', repository=ORG_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
(url_for('create_token', repository=PRIVATE_REPO),
|
||||
(401, open_kwargs('POST'))),
|
||||
|
||||
(url_for('change_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('PUT'))),
|
||||
(url_for('change_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('PUT'))),
|
||||
(url_for('change_token', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
(url_for('delete_token', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(401, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('subscribe_api'), (401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('subscribe_org_api', orgname=ORG), (401, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('get_subscription'), (401, open_kwargs())),
|
||||
|
||||
(url_for('get_org_subscription', orgname=ORG), (401, open_kwargs())),
|
||||
])
|
||||
|
||||
|
||||
def build_no_access_spec():
|
||||
changes = OrderedDict([
|
||||
(url_for('change_user_details'), (200, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('get_matching_users', prefix='dev'), (200, open_kwargs())),
|
||||
|
||||
(url_for('get_matching_entities', prefix='dev'), (200, open_kwargs())),
|
||||
|
||||
(url_for('get_organization', orgname=ORG), (403, open_kwargs())),
|
||||
|
||||
(url_for('get_organization_private_allowed', orgname=ORG),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('update_organization_team', orgname=ORG, teamname=ORG_OWNERS),
|
||||
(403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_organization_team', orgname=ORG, teamname=ORG_OWNERS),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('get_organization_team_members', orgname=ORG,
|
||||
teamname=ORG_OWNERS), (403, open_kwargs())),
|
||||
|
||||
(url_for('update_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
(403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('create_repo_api'), (403, open_kwargs('POST'))),
|
||||
|
||||
(url_for('update_repo_api', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs('PUT'))),
|
||||
(url_for('update_repo_api', repository=ORG_REPO),
|
||||
(403, open_kwargs('PUT'))),
|
||||
(url_for('update_repo_api', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('change_repo_visibility_api', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('change_repo_visibility_api', repository=ORG_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('change_repo_visibility_api', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
|
||||
(url_for('delete_repository', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_repository', repository=ORG_REPO),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_repository', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('get_repo_builds', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('get_repo_builds', repository=ORG_REPO), (403, open_kwargs())),
|
||||
(url_for('get_repo_builds', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('get_filedrop_url'), (400, open_kwargs('POST'))),
|
||||
|
||||
(url_for('request_repo_build', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('request_repo_build', repository=ORG_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('request_repo_build', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
|
||||
(url_for('list_repo_team_permissions', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repo_team_permissions', repository=ORG_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repo_team_permissions', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('list_repo_user_permissions', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repo_user_permissions', repository=ORG_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repo_user_permissions', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('get_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs())),
|
||||
(url_for('get_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs())),
|
||||
(url_for('get_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs())),
|
||||
|
||||
(url_for('get_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs())),
|
||||
(url_for('get_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs())),
|
||||
(url_for('get_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs())),
|
||||
|
||||
(url_for('change_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('PUT'))),
|
||||
(url_for('change_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('PUT'))),
|
||||
(url_for('change_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('change_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('PUT'))),
|
||||
(url_for('change_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('PUT'))),
|
||||
(url_for('change_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), (403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('delete_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_team_permissions', repository=ORG_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=FAKE_TEAMNAME), (403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('list_repo_tokens', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs())),
|
||||
(url_for('list_repo_tokens', repository=ORG_REPO), (403, open_kwargs())),
|
||||
(url_for('list_repo_tokens', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('get_tokens', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs())),
|
||||
(url_for('get_tokens', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs())),
|
||||
(url_for('get_tokens', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs())),
|
||||
|
||||
(url_for('create_token', repository=PUBLIC_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('create_token', repository=ORG_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
(url_for('create_token', repository=PRIVATE_REPO),
|
||||
(403, open_kwargs('POST'))),
|
||||
|
||||
(url_for('change_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('PUT'))),
|
||||
(url_for('change_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('PUT'))),
|
||||
(url_for('change_token', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('delete_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
(url_for('delete_token', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
(403, open_kwargs('DELETE'))),
|
||||
|
||||
(url_for('subscribe_api'), (403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('subscribe_org_api', orgname=ORG), (403, open_kwargs('PUT'))),
|
||||
|
||||
(url_for('get_subscription'), (200, open_kwargs())),
|
||||
|
||||
(url_for('get_org_subscription', orgname=ORG), (403, open_kwargs())),
|
||||
])
|
||||
|
||||
to_update = build_anon_spec()
|
||||
to_update.update(changes)
|
||||
return to_update
|
||||
def set_data_from_obj(self, json_serializable):
|
||||
self._data = json.dumps(json_serializable)
|
||||
return self
|
||||
|
||||
def set_method(self, method):
|
||||
self._method = method
|
||||
return self
|
||||
|
||||
def get_client_args(self):
|
||||
kwargs = {
|
||||
'method': self._method
|
||||
}
|
||||
|
||||
if self._data or self._method == 'POST' or self._method == 'PUT':
|
||||
kwargs['data'] = self._data if self._data else '{}'
|
||||
kwargs['content_type'] = 'application/json'
|
||||
|
||||
return self._url, kwargs
|
||||
|
||||
|
||||
def build_specs():
|
||||
return [
|
||||
TestSpec(url_for('welcome'), 200, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('plans_list'), 200, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_logged_in_user'), 200, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('change_user_details'),
|
||||
401, 200, 200, 200).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('create_user_api'), 201, 201, 201,
|
||||
201).set_method('POST').set_data_from_obj(NEW_USER_DETAILS),
|
||||
|
||||
TestSpec(url_for('signin_api'), 200, 200, 200,
|
||||
200).set_method('POST').set_data_from_obj(SIGNIN_DETAILS),
|
||||
|
||||
TestSpec(url_for('send_recovery'), 201, 201, 201,
|
||||
201).set_method('POST').set_data_from_obj(SEND_RECOVERY_DETAILS),
|
||||
|
||||
TestSpec(url_for('get_matching_users', prefix='dev'), 401, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_matching_entities', prefix='dev'), 401, 200, 200,
|
||||
200),
|
||||
|
||||
TestSpec(url_for('get_organization', orgname=ORG), 401, 403, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_organization_private_allowed', orgname=ORG)),
|
||||
|
||||
TestSpec(url_for('update_organization_team', orgname=ORG,
|
||||
teamname=ORG_OWNERS)).set_method('PUT'),
|
||||
TestSpec(url_for('update_organization_team', orgname=ORG,
|
||||
teamname=ORG_READERS)).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('delete_organization_team', orgname=ORG,
|
||||
teamname=ORG_OWNERS),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_organization_team', orgname=ORG,
|
||||
teamname=ORG_READERS),
|
||||
admin_code=204).set_method('DELETE'),
|
||||
|
||||
TestSpec(url_for('get_organization_team_members', orgname=ORG,
|
||||
teamname=ORG_OWNERS)),
|
||||
TestSpec(url_for('get_organization_team_members', orgname=ORG,
|
||||
teamname=ORG_READERS), read_code=200),
|
||||
|
||||
TestSpec(url_for('update_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
admin_code=400).set_method('PUT'),
|
||||
TestSpec(url_for('update_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_READERS,
|
||||
membername=ORG_OWNER)).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('delete_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_OWNERS, membername=ORG_OWNER),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_organization_team_member', orgname=ORG,
|
||||
teamname=ORG_READERS, membername=ORG_OWNER),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
|
||||
(TestSpec(url_for('create_repo_api'))
|
||||
.set_method('POST')
|
||||
.set_data_from_obj(NEW_ORG_REPO_DETAILS)),
|
||||
|
||||
TestSpec(url_for('match_repos_api'), 200, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('list_repos_api'), 200, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('update_repo_api', repository=PUBLIC_REPO),
|
||||
admin_code=403).set_method('PUT'),
|
||||
(TestSpec(url_for('update_repo_api', repository=ORG_REPO))
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(UPDATE_REPO_DETAILS)),
|
||||
(TestSpec(url_for('update_repo_api', repository=PRIVATE_REPO))
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(UPDATE_REPO_DETAILS)),
|
||||
|
||||
(TestSpec(url_for('change_repo_visibility_api', repository=PUBLIC_REPO),
|
||||
admin_code=403).set_method('POST')
|
||||
.set_data_from_obj(CHANGE_VISIBILITY_DETAILS)),
|
||||
(TestSpec(url_for('change_repo_visibility_api', repository=ORG_REPO))
|
||||
.set_method('POST').set_data_from_obj(CHANGE_VISIBILITY_DETAILS)),
|
||||
(TestSpec(url_for('change_repo_visibility_api', repository=PRIVATE_REPO))
|
||||
.set_method('POST').set_data_from_obj(CHANGE_VISIBILITY_DETAILS)),
|
||||
|
||||
TestSpec(url_for('delete_repository', repository=PUBLIC_REPO),
|
||||
admin_code=403).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_repository', repository=ORG_REPO),
|
||||
admin_code=204).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_repository', repository=PRIVATE_REPO),
|
||||
admin_code=204).set_method('DELETE'),
|
||||
|
||||
TestSpec(url_for('get_repo_api', repository=PUBLIC_REPO),
|
||||
200, 200, 200,200),
|
||||
TestSpec(url_for('get_repo_api', repository=ORG_REPO),
|
||||
403, 403, 200, 200),
|
||||
TestSpec(url_for('get_repo_api', repository=PRIVATE_REPO),
|
||||
403, 403, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_repo_builds', repository=PUBLIC_REPO),
|
||||
admin_code=403),
|
||||
TestSpec(url_for('get_repo_builds', repository=ORG_REPO)),
|
||||
TestSpec(url_for('get_repo_builds', repository=PRIVATE_REPO)),
|
||||
|
||||
TestSpec(url_for('get_filedrop_url'), 401, 200, 200,
|
||||
200).set_method('POST').set_data_from_obj(FILE_DROP_DETAILS),
|
||||
|
||||
(TestSpec(url_for('request_repo_build', repository=PUBLIC_REPO),
|
||||
admin_code=403).set_method('POST')
|
||||
.set_data_from_obj(CREATE_BUILD_DETAILS)),
|
||||
(TestSpec(url_for('request_repo_build', repository=ORG_REPO),
|
||||
admin_code=201).set_method('POST')
|
||||
.set_data_from_obj(CREATE_BUILD_DETAILS)),
|
||||
(TestSpec(url_for('request_repo_build', repository=PRIVATE_REPO),
|
||||
admin_code=201).set_method('POST')
|
||||
.set_data_from_obj(CREATE_BUILD_DETAILS)),
|
||||
|
||||
TestSpec(url_for('list_repository_images', repository=PUBLIC_REPO),
|
||||
200, 200, 200, 200),
|
||||
TestSpec(url_for('list_repository_images', repository=ORG_REPO),
|
||||
403, 403, 200, 200),
|
||||
TestSpec(url_for('list_repository_images', repository=PRIVATE_REPO),
|
||||
403, 403, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_image', repository=PUBLIC_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 404, 404, 404, 404),
|
||||
TestSpec(url_for('get_image', repository=ORG_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 403, 403, 404, 404),
|
||||
TestSpec(url_for('get_image', repository=PRIVATE_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 403, 403, 404, 404),
|
||||
|
||||
TestSpec(url_for('get_image_changes', repository=PUBLIC_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 404, 404, 404, 404),
|
||||
TestSpec(url_for('get_image_changes', repository=ORG_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 403, 403, 404, 404),
|
||||
TestSpec(url_for('get_image_changes', repository=PRIVATE_REPO,
|
||||
image_id=FAKE_IMAGE_ID), 403, 403, 404, 404),
|
||||
|
||||
TestSpec(url_for('list_tag_images', repository=PUBLIC_REPO,
|
||||
tag=FAKE_TAG_NAME), 404, 404, 404, 404),
|
||||
TestSpec(url_for('list_tag_images', repository=ORG_REPO,
|
||||
tag=FAKE_TAG_NAME), 403, 403, 404, 404),
|
||||
TestSpec(url_for('list_tag_images', repository=PRIVATE_REPO,
|
||||
tag=FAKE_TAG_NAME), 403, 403, 404, 404),
|
||||
|
||||
TestSpec(url_for('list_repo_team_permissions', repository=PUBLIC_REPO),
|
||||
admin_code=403),
|
||||
TestSpec(url_for('list_repo_team_permissions', repository=ORG_REPO)),
|
||||
TestSpec(url_for('list_repo_team_permissions', repository=PRIVATE_REPO)),
|
||||
|
||||
TestSpec(url_for('list_repo_user_permissions', repository=PUBLIC_REPO),
|
||||
admin_code=403),
|
||||
TestSpec(url_for('list_repo_user_permissions', repository=ORG_REPO)),
|
||||
TestSpec(url_for('list_repo_user_permissions', repository=PRIVATE_REPO)),
|
||||
|
||||
TestSpec(url_for('get_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME), admin_code=403),
|
||||
TestSpec(url_for('get_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME), admin_code=400),
|
||||
TestSpec(url_for('get_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME), admin_code=400),
|
||||
|
||||
TestSpec(url_for('get_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_OWNERS), admin_code=403),
|
||||
TestSpec(url_for('get_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_READERS), admin_code=403),
|
||||
TestSpec(url_for('get_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_OWNERS), admin_code=400),
|
||||
TestSpec(url_for('get_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_READERS)),
|
||||
TestSpec(url_for('get_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_OWNERS), admin_code=400),
|
||||
TestSpec(url_for('get_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_READERS), admin_code=400),
|
||||
|
||||
TestSpec(url_for('change_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=403).set_method('PUT'),
|
||||
TestSpec(url_for('change_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=400).set_method('PUT'),
|
||||
TestSpec(url_for('change_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=400).set_method('PUT'),
|
||||
|
||||
(TestSpec(url_for('change_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_OWNERS), admin_code=403)
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
(TestSpec(url_for('change_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_READERS), admin_code=403)
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
(TestSpec(url_for('change_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_OWNERS))
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
(TestSpec(url_for('change_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_READERS))
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
(TestSpec(url_for('change_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_OWNERS), admin_code=400)
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
(TestSpec(url_for('change_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_READERS), admin_code=400)
|
||||
.set_method('PUT')
|
||||
.set_data_from_obj(CHANGE_PERMISSION_DETAILS)),
|
||||
|
||||
TestSpec(url_for('delete_user_permissions', repository=PUBLIC_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=403).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_user_permissions', repository=ORG_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_user_permissions', repository=PRIVATE_REPO,
|
||||
username=FAKE_USERNAME),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
|
||||
TestSpec(url_for('delete_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_OWNERS),
|
||||
admin_code=403).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_team_permissions', repository=PUBLIC_REPO,
|
||||
teamname=ORG_READERS),
|
||||
admin_code=403).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_OWNERS),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_team_permissions', repository=ORG_REPO,
|
||||
teamname=ORG_READERS),
|
||||
admin_code=204).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_OWNERS),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_team_permissions', repository=PRIVATE_REPO,
|
||||
teamname=ORG_READERS),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
|
||||
TestSpec(url_for('list_repo_tokens', repository=PUBLIC_REPO),
|
||||
admin_code=403),
|
||||
TestSpec(url_for('list_repo_tokens', repository=ORG_REPO)),
|
||||
TestSpec(url_for('list_repo_tokens', repository=PRIVATE_REPO)),
|
||||
|
||||
TestSpec(url_for('get_tokens', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
admin_code=403),
|
||||
TestSpec(url_for('get_tokens', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
admin_code=400),
|
||||
TestSpec(url_for('get_tokens', repository=PRIVATE_REPO, code=FAKE_TOKEN),
|
||||
admin_code=400),
|
||||
|
||||
TestSpec(url_for('create_token', repository=PUBLIC_REPO),
|
||||
admin_code=403).set_method('POST'),
|
||||
(TestSpec(url_for('create_token', repository=ORG_REPO),
|
||||
admin_code=201).set_method('POST')
|
||||
.set_data_from_obj(CREATE_TOKEN_DETAILS)),
|
||||
(TestSpec(url_for('create_token', repository=PRIVATE_REPO),
|
||||
admin_code=201).set_method('POST')
|
||||
.set_data_from_obj(CREATE_TOKEN_DETAILS)),
|
||||
|
||||
TestSpec(url_for('change_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
admin_code=403).set_method('PUT'),
|
||||
TestSpec(url_for('change_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
admin_code=400).set_method('PUT'),
|
||||
TestSpec(url_for('change_token', repository=PRIVATE_REPO,
|
||||
code=FAKE_TOKEN), admin_code=400).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('delete_token', repository=PUBLIC_REPO, code=FAKE_TOKEN),
|
||||
admin_code=403).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_token', repository=ORG_REPO, code=FAKE_TOKEN),
|
||||
admin_code=400).set_method('DELETE'),
|
||||
TestSpec(url_for('delete_token', repository=PRIVATE_REPO,
|
||||
code=FAKE_TOKEN), admin_code=400).set_method('DELETE'),
|
||||
|
||||
TestSpec(url_for('subscribe_api'), 401, 400, 400, 400).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('subscribe_org_api', orgname=ORG),
|
||||
401, 403, 403, 400).set_method('PUT'),
|
||||
|
||||
TestSpec(url_for('get_subscription'), 401, 200, 200, 200),
|
||||
|
||||
TestSpec(url_for('get_org_subscription', orgname=ORG)),
|
||||
]
|
||||
|
|
|
@ -6,10 +6,12 @@ import endpoints.api
|
|||
from app import app
|
||||
from data import model
|
||||
from initdb import wipe_database, initialize_database, populate_database
|
||||
from specs import build_anon_spec, build_no_access_spec
|
||||
from specs import build_specs
|
||||
|
||||
|
||||
NO_ACCESS_USER = 'freshuser'
|
||||
READ_ACCESS_USER = 'reader'
|
||||
ADMIN_ACCESS_USER = 'devtable'
|
||||
|
||||
|
||||
class ApiTestCase(unittest.TestCase):
|
||||
|
@ -19,31 +21,78 @@ class ApiTestCase(unittest.TestCase):
|
|||
populate_database()
|
||||
|
||||
|
||||
class SpecTestBuilder(type):
|
||||
@staticmethod
|
||||
def _test_generator(url, expected_status, open_kwargs, auth_username=None):
|
||||
def test(self):
|
||||
with app.test_client() as c:
|
||||
if auth_username:
|
||||
# Temporarily remove the teardown functions
|
||||
teardown_funcs = app.teardown_request_funcs[None]
|
||||
app.teardown_request_funcs[None] = []
|
||||
|
||||
with c.session_transaction() as sess:
|
||||
sess['user_id'] = auth_username
|
||||
sess['identity.id'] = auth_username
|
||||
sess['identity.auth_type'] = 'username'
|
||||
|
||||
# Restore the teardown functions
|
||||
app.teardown_request_funcs[None] = teardown_funcs
|
||||
|
||||
rv = c.open(url, **open_kwargs)
|
||||
msg = '%s %s: %s expected: %s' % (open_kwargs['method'], url,
|
||||
rv.status_code, expected_status)
|
||||
if rv.status_code != expected_status:
|
||||
print msg
|
||||
self.assertEqual(rv.status_code, expected_status, msg)
|
||||
return test
|
||||
|
||||
|
||||
def __new__(cls, name, bases, attrs):
|
||||
with app.test_request_context() as ctx:
|
||||
specs = attrs['spec_func']()
|
||||
for test_spec in specs:
|
||||
url, open_kwargs = test_spec.get_client_args()
|
||||
expected_status = getattr(test_spec, attrs['result_attr'])
|
||||
test = SpecTestBuilder._test_generator(url, expected_status,
|
||||
open_kwargs,
|
||||
attrs['auth_username'])
|
||||
|
||||
test_name_url = url.replace('/', '_').replace('-', '_')
|
||||
test_name = 'test_%s_%s' % (open_kwargs['method'].lower(),
|
||||
test_name_url)
|
||||
attrs[test_name] = test
|
||||
|
||||
return type(name, bases, attrs)
|
||||
|
||||
|
||||
class TestAnonymousAccess(ApiTestCase):
|
||||
def __runspec(self, client, spec):
|
||||
for url, (expected_status, open_kwargs) in spec.items():
|
||||
rv = client.open(url, **open_kwargs)
|
||||
msg = '%s %s: %s expected: %s' % (open_kwargs['method'], url,
|
||||
rv.status_code, expected_status)
|
||||
self.assertEqual(rv.status_code, expected_status, msg)
|
||||
__metaclass__ = SpecTestBuilder
|
||||
spec_func = build_specs
|
||||
result_attr = 'anon_code'
|
||||
auth_username = None
|
||||
|
||||
def test_anonymous_public_access(self):
|
||||
with app.test_request_context() as ctx:
|
||||
spec = build_anon_spec()
|
||||
|
||||
with app.test_client() as c:
|
||||
self.__runspec(c, spec)
|
||||
class TestNoAccess(ApiTestCase):
|
||||
__metaclass__ = SpecTestBuilder
|
||||
spec_func = build_specs
|
||||
result_attr = 'no_access_code'
|
||||
auth_username = NO_ACCESS_USER
|
||||
|
||||
def test_authenticated_but_not_authorized(self):
|
||||
with app.test_request_context() as ctx:
|
||||
spec = build_no_access_spec()
|
||||
|
||||
with app.test_client() as c:
|
||||
with c.session_transaction() as sess:
|
||||
sess['user_id'] = NO_ACCESS_USER
|
||||
class TestReadAccess(ApiTestCase):
|
||||
__metaclass__ = SpecTestBuilder
|
||||
spec_func = build_specs
|
||||
result_attr = 'read_code'
|
||||
auth_username = READ_ACCESS_USER
|
||||
|
||||
self.__runspec(c, spec)
|
||||
|
||||
class TestAdminAccess(ApiTestCase):
|
||||
__metaclass__ = SpecTestBuilder
|
||||
spec_func = build_specs
|
||||
result_attr = 'admin_code'
|
||||
auth_username = ADMIN_ACCESS_USER
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
37
test/teststorage.py
Normal file
37
test/teststorage.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from uuid import uuid4
|
||||
|
||||
from storage.basestorage import Storage
|
||||
|
||||
|
||||
class FakeStorage(Storage):
|
||||
def _init_path(self, path=None, create=False):
|
||||
return path
|
||||
|
||||
def get_content(self, path):
|
||||
raise IOError('Fake files are fake!')
|
||||
|
||||
def put_content(self, path, content):
|
||||
return path
|
||||
|
||||
def stream_read(self, path):
|
||||
yield ''
|
||||
|
||||
def stream_write(self, path, fp):
|
||||
pass
|
||||
|
||||
def remove(self, path):
|
||||
pass
|
||||
|
||||
def exists(self, path):
|
||||
return True
|
||||
|
||||
|
||||
class FakeUserfiles(object):
|
||||
def prepare_for_drop(self, mime_type):
|
||||
return ('http://fake/url', uuid4())
|
||||
|
||||
def store_file(self, flask_file):
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_file_url(self, file_id, expires_in=300):
|
||||
return ('http://fake/url')
|
|
@ -13,7 +13,6 @@ from base64 import b64encode
|
|||
from requests.exceptions import ConnectionError
|
||||
|
||||
from data.queue import dockerfile_build_queue
|
||||
from data.userfiles import UserRequestFiles
|
||||
from data import model
|
||||
from data.database import db as db_connection
|
||||
from app import app
|
||||
|
@ -151,9 +150,7 @@ def babysit_builder(request):
|
|||
ssh_client.exec_command(remove_auth_cmd)
|
||||
|
||||
# Prepare the signed resource url the build node can fetch the job from
|
||||
user_files = UserRequestFiles(app.config['AWS_ACCESS_KEY'],
|
||||
app.config['AWS_SECRET_KEY'],
|
||||
app.config['REGISTRY_S3_BUCKET'])
|
||||
user_files = app.config['USERFILES']
|
||||
resource_url = user_files.get_file_url(repository_build.resource_key)
|
||||
|
||||
# Start the build server
|
||||
|
|
Reference in a new issue