Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jsam committed Nov 22, 2019
1 parent 6790e61 commit 92220ba
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 88 deletions.
93 changes: 90 additions & 3 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,16 +580,22 @@ def svc_client(mock_redis):
def svc_client_with_repo(svc_client, mock_redis):
"""Renku service remote repository."""
remote_url = 'https://renkulab.io/gitlab/contact/integration-tests.git'
headers = {'Authorization': 'Bearer b4b4de0eda0f471ab82702bd5c367fa7'}
headers = {
'Content-Type': 'application/json',
'accept': 'application/json',
'Authorization': 'Bearer b4b4de0eda0f471ab82702bd5c367fa7',
}

params = {
payload = {
'git_url': remote_url,
'git_username': 'contact',
'git_access_token': 'EcfPJvEqjJepyu6XyqKZ',
}

response = svc_client.post(
'/cache/project-clone', data=params, headers=headers
'/cache/project-clone',
data=json.dumps(payload),
headers=headers,
)

assert response
Expand All @@ -599,3 +605,84 @@ def svc_client_with_repo(svc_client, mock_redis):
assert isinstance(uuid.UUID(project_id), uuid.UUID)

yield svc_client, headers, project_id


@pytest.fixture(
params=[
{
'url': '/cache/files-list',
'allowed_method': 'GET',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/cache/files-upload',
'allowed_method': 'POST',
'headers': {}
},
{
'url': '/cache/project-clone',
'allowed_method': 'POST',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/cache/project-list',
'allowed_method': 'GET',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/datasets/add',
'allowed_method': 'POST',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/datasets/create',
'allowed_method': 'POST',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/datasets/files-list',
'allowed_method': 'GET',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
{
'url': '/datasets/list',
'allowed_method': 'GET',
'headers': {
'Content-Type': 'application/json',
'accept': 'application/json',
}
},
]
)
def service_allowed_endpoint(request, svc_client, mock_redis):
"""Ensure allowed methods and correct headers."""
methods = {
'GET': svc_client.get,
'POST': svc_client.post,
'HEAD': svc_client.head,
'PUT': svc_client.put,
'DELETE': svc_client.delete,
'OPTIONS': svc_client.options,
'TRACE': svc_client.trace,
'PATCH': svc_client.patch,
}

yield methods, request.param, svc_client
2 changes: 1 addition & 1 deletion renku/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
option_use_external_storage
from renku.core.commands.version import check_version, print_version
from renku.core.management.client import LocalClient
from renku.core.management.config import ConfigManagerMixin, RENKU_HOME
from renku.core.management.config import RENKU_HOME, ConfigManagerMixin
from renku.core.management.repository import default_path

#: Monkeypatch Click application.
Expand Down
1 change: 1 addition & 0 deletions renku/service/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
RENKU_EXCEPTION_ERROR_CODE = -32100
REDIS_EXCEPTION_ERROR_CODE = -32200

INVALID_HEADERS_ERROR_CODE = -32601
INVALID_PARAMS_ERROR_CODE = -32602
INTERNAL_FAILURE_ERROR_CODE = -32603

Expand Down
12 changes: 8 additions & 4 deletions renku/service/serializers/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,18 @@ class FileListResponseRPC(JsonRPCResponse):
class ProjectCloneRequest(Schema):
"""Request schema for project clone."""

project_id = fields.String(missing=lambda: uuid.uuid4().hex)
name = fields.String(required=True)
owner = fields.String(required=True)

git_url = fields.String(required=True)
git_username = fields.String(required=True)
git_access_token = fields.String(required=True)


class ProjectCloneDetails(ProjectCloneRequest):
"""Details schema for project clone."""

project_id = fields.String(missing=lambda: uuid.uuid4().hex)
name = fields.String(required=True)
owner = fields.String(required=True)

@validates('git_url')
def validate_git_url(self, value):
"""Validates git url."""
Expand Down
1 change: 1 addition & 0 deletions renku/service/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# limitations under the License.
"""Renku service utility functions."""
from git import Repo

from renku.service.config import CACHE_PROJECTS_PATH, CACHE_UPLOADS_PATH


Expand Down
17 changes: 10 additions & 7 deletions renku/service/views/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
INVALID_PARAMS_ERROR_CODE, SUPPORTED_ARCHIVES
from renku.service.serializers.cache import FileListResponse, \
FileListResponseRPC, FileUploadDetails, FileUploadRequest, \
FileUploadResponse, FileUploadResponseRPC, ProjectCloneRequest, \
ProjectCloneResponse, ProjectCloneResponseRPC, ProjectListResponse, \
ProjectListResponseRPC, extract_file
FileUploadResponse, FileUploadResponseRPC, ProjectCloneDetails, \
ProjectCloneRequest, ProjectCloneResponse, ProjectCloneResponseRPC, \
ProjectListResponse, ProjectListResponseRPC, extract_file
from renku.service.utils import make_file_path, make_project_path
from renku.service.views.decorators import handle_base_except, \
from renku.service.views.decorators import accepts_json, handle_base_except, \
handle_git_except, handle_renku_except, handle_validation_except, \
header_doc, requires_cache, requires_identity

Expand Down Expand Up @@ -156,7 +156,10 @@ def upload_file_view(user, cache):

@use_kwargs(ProjectCloneRequest)
@marshal_with(ProjectCloneResponseRPC)
@header_doc('Clone a remote project.', tags=(CACHE_BLUEPRINT_TAG, ))
@header_doc(
'Clone a remote project. If the project is cached already, '
'new clone operation will override the old cache state.',
tags=(CACHE_BLUEPRINT_TAG, ))
@cache_blueprint.route(
'/cache/project-clone',
methods=['POST'],
Expand All @@ -168,10 +171,10 @@ def upload_file_view(user, cache):
@handle_validation_except
@requires_cache
@requires_identity
@accepts_json
def project_clone(user, cache):
"""Clone a remote repository."""
ctx = ProjectCloneRequest().load(dict(request.form))

ctx = ProjectCloneDetails().load(request.json)
local_path = make_project_path(user, ctx)
if local_path.exists():
shutil.rmtree(local_path)
Expand Down
8 changes: 5 additions & 3 deletions renku/service/views/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
DatasetFilesListResponseRPC, DatasetListRequest, DatasetListResponse, \
DatasetListResponseRPC
from renku.service.utils import make_file_path, make_project_path, repo_sync
from renku.service.views.decorators import handle_base_except, \
from renku.service.views.decorators import accepts_json, handle_base_except, \
handle_git_except, handle_renku_except, handle_validation_except, \
header_doc, requires_cache, requires_identity

Expand Down Expand Up @@ -137,11 +137,12 @@ def list_dataset_files_view(user, cache):
@handle_git_except
@handle_renku_except
@handle_validation_except
@accepts_json
@requires_cache
@requires_identity
def add_file_to_dataset_view(user, cache):
"""Add uploaded file to cloned repository."""
ctx = DatasetAddRequest().load(request.form)
ctx = DatasetAddRequest().load(request.json)
project = cache.get_project(user, ctx['project_id'])
file = cache.get_file(user, ctx['file_id'])

Expand Down Expand Up @@ -196,11 +197,12 @@ def add_file_to_dataset_view(user, cache):
@handle_git_except
@handle_renku_except
@handle_validation_except
@accepts_json
@requires_cache
@requires_identity
def create_dataset_view(user, cache):
"""Create a new dataset in a project."""
ctx = DatasetCreateRequest().load(request.form)
ctx = DatasetCreateRequest().load(request.json)
project = cache.get_project(user, ctx['project_id'])

project_path = make_project_path(user, project)
Expand Down
33 changes: 30 additions & 3 deletions renku/service/views/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
from renku.core.errors import RenkuException
from renku.service.config import GIT_ACCESS_DENIED_ERROR_CODE, \
GIT_UNKNOWN_ERROR_CODE, INTERNAL_FAILURE_ERROR_CODE, \
INVALID_PARAMS_ERROR_CODE, REDIS_EXCEPTION_ERROR_CODE, \
RENKU_EXCEPTION_ERROR_CODE
INVALID_HEADERS_ERROR_CODE, INVALID_PARAMS_ERROR_CODE, \
REDIS_EXCEPTION_ERROR_CODE, RENKU_EXCEPTION_ERROR_CODE


def requires_identity(f):
Expand All @@ -42,7 +42,7 @@ def decorated_function(*args, **kws):
if user and not user[0]:
return jsonify(
error={
'code': INVALID_PARAMS_ERROR_CODE,
'code': INVALID_HEADERS_ERROR_CODE,
'reason': 'user identification is missing'
}
)
Expand Down Expand Up @@ -146,6 +146,33 @@ def decorated_function(*args, **kwargs):
return decorated_function


def accepts_json(f):
"""Wrapper which ensures only JSON payload can be in request."""
# nowa
@wraps(f)
def decorated_function(*args, **kwargs):
"""Represents decorated function."""
if 'Content-Type' not in request.headers:
return jsonify(
error={
'code': INVALID_HEADERS_ERROR_CODE,
'reason': 'invalid request headers'
}
)

header_check = request.headers['Content-Type'] == 'application/json'

if not request.is_json or not header_check:
return jsonify(error={
'code': INVALID_HEADERS_ERROR_CODE,
'reason': 'invalid request payload'
})

return f(*args, **kwargs)

return decorated_function


def handle_base_except(f):
"""Wrapper which handles base exceptions."""
# nowa
Expand Down
Loading

0 comments on commit 92220ba

Please sign in to comment.