Skip to content

Commit

Permalink
EP-3352 Open-EO#34 Update process graph handling in /services
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Apr 15, 2020
1 parent d0ba9d8 commit 571319d
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 25 deletions.
22 changes: 22 additions & 0 deletions dummy_impl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numbers
import os
from typing import List
from unittest.mock import Mock

from shapely.geometry import Polygon, MultiPolygon
Expand Down Expand Up @@ -88,6 +89,27 @@ def service_types(self) -> dict:
}
}

def list_services(self) -> List[dict]:
return [
{
'id': 'wmts-foo',
'type': ' WMTS',
'url': 'https://oeo.net/wmts/foo',
'enabled': True
}
]

def service_info(self, service_id: str) -> dict:
assert service_id == 'wmts-foo'
return {
'id': 'wmts-foo',
'type': 'WMTS',
'process': {'process_graph': {"foo": {"process_id": "foo", "arguments": {}}}},
'url': 'https://oeo.net/wmts/foo',
'enabled': True,
'parameters': {},
'attributes': {},
}

class DummyCatalog(CollectionCatalog):
_COLLECTIONS = [{
Expand Down
15 changes: 5 additions & 10 deletions openeo_driver/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,37 +31,32 @@ def service_types(self) -> dict:

def list_services(self) -> List[dict]:
"""https://open-eo.github.io/openeo-api/apireference/#tag/Secondary-Services-Management/paths/~1services/get"""
# TODO require auth/user handle?
# TODO: encapsulate service info in a predefined struct instead of free form dict? #8
return []

def service_info(self, service_id: str) -> dict:
"""https://open-eo.github.io/openeo-api/apireference/#tag/Secondary-Services-Management/paths/~1services~1{service_id}/get"""
# TODO require auth/user handle?
# TODO: encapsulate service info in a predefined struct instead of free form dict? #8
raise NotImplementedError()

def create_service(self, data: dict) -> Tuple[str, str]:
def create_service(self, process_graph: dict, service_type: str, api_version: str, post_data: dict) -> Tuple[str, str]:
"""
https://open-eo.github.io/openeo-api/apireference/#tag/Secondary-Services-Management/paths/~1services/post
:return: (location, openeo_identifier)
"""
from openeo_driver.ProcessGraphDeserializer import evaluate
# TODO require auth/user handle?
process_graph = data['process_graph']

service_type = data['type']
if service_type.lower() not in set(st.lower() for st in self.service_types()):
raise OpenEOApiException(
message="Secondary service type {t!r} is not supported.".format(t=service_type),
code="ServiceUnsupported", status_code=400
)

# TODO: avoid passing api version?
api_version = data.pop('api_version')
image_collection = evaluate(process_graph, viewingParameters={'version': api_version})
service_info = image_collection.tiled_viewing_service(**data)
service_info = image_collection.tiled_viewing_service(service_type=service_type, process_graph=process_graph, post_data=post_data)
return service_info['url'], service_info.get('service_id', 'unknown')

def update_service(self, service_id: str, data: dict) -> None:
def update_service(self, service_id: str, process_graph: dict) -> None:
"""https://open-eo.github.io/openeo-api/apireference/#tag/Secondary-Services-Management/paths/~1services~1{service_id}/patch"""
# TODO require auth/user handle?
raise NotImplementedError()
Expand Down
28 changes: 19 additions & 9 deletions openeo_driver/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,10 +572,13 @@ def services_post():
:return:
"""
# TODO require authenticated user
data = request.get_json()
# TODO avoid passing api version this hackish way?
data['api_version'] = g.version
url, identifier = backend_implementation.secondary_services.create_service(data)
post_data = request.get_json()
url, identifier = backend_implementation.secondary_services.create_service(
process_graph=_extract_process_graph(post_data),
service_type=post_data["type"],
api_version=g.version,
post_data=post_data,
)

return make_response('', 201, {
'Content-Type': 'application/json',
Expand All @@ -589,23 +592,30 @@ def services_post():
def services_get():
"""List all running secondary web services for authenticated user"""
# TODO Require authentication
return jsonify(backend_implementation.secondary_services.list_services())
return jsonify({
# TODO: encapsulate service info in a predefined struct instead of free form dict? #8
"services": backend_implementation.secondary_services.list_services(),
"links": [],
})


@api_endpoint
@openeo_bp.route('/services/<service_id>', methods=['GET'])
def get_service_info(service_id):
# TODO Require authentication
return jsonify(backend_implementation.secondary_services.service_info(service_id))
service_info = backend_implementation.secondary_services.service_info(service_id)
# TODO: encapsulate service info in a predefined struct instead of free form dict? #8
if requested_api_version().below("1.0.0"):
service_info["process_graph"] = service_info["process"]["process_graph"]
return jsonify(service_info)


@api_endpoint
@openeo_bp.route('/services/<service_id>', methods=['PATCH'])
def service_patch(service_id):
# TODO Require authentication
data = request.get_json()
# TODO sanitize/check data?
backend_implementation.secondary_services.update_service(service_id, data=data)
process_graph = _extract_process_graph(request.get_json())
backend_implementation.secondary_services.update_service(service_id, process_graph=process_graph)
return response_204_no_content()


Expand Down
50 changes: 50 additions & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,56 @@ def test_uncaught_exceptions_return_InternalServerError(self):

self.assertEqual(500, resp.status_code)

def test_list_services_040(self):
metadata = self.client.get('/openeo/0.4.0/services').json
assert metadata == {
"services": [{
'id': 'wmts-foo',
'type': ' WMTS',
'enabled': True,
'url': 'https://oeo.net/wmts/foo'
}],
"links": []
}

def test_list_services_100(self):
metadata = self.client.get('/openeo/1.0.0/services').json
assert metadata == {
"services": [{
'id': 'wmts-foo',
'type': ' WMTS',
'enabled': True,
'url': 'https://oeo.net/wmts/foo'
}],
"links": []
}

def test_get_service_metadata_040(self):
metadata = self.client.get('/openeo/0.4.0/services/wmts-foo').json
expected = {
"id": "wmts-foo",
"process_graph": {"foo": {"process_id": "foo", "arguments": {}}},
"url": "https://oeo.net/wmts/foo",
"type": "WMTS",
"enabled": True,
"parameters": {},
"attributes": {},
}
assert {k: metadata[k] for k in expected.keys()} == expected

def test_get_service_metadata_100(self):
metadata = self.client.get('/openeo/1.0.0/services/wmts-foo').json
expected = {
"id": "wmts-foo",
"process": {"process_graph": {"foo": {"process_id": "foo", "arguments": {}}}},
"url": "https://oeo.net/wmts/foo",
"type": "WMTS",
"enabled": True,
"attributes": {},
}
assert {k: metadata[k] for k in expected.keys()} == expected


def test_get_batch_job_logs(self):
resp = self.client.get('/openeo/jobs/07024ee9-7847-4b8a-b260-6c879a2b3cdc/logs', headers=self._auth_header)

Expand Down
42 changes: 36 additions & 6 deletions tests/test_views_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,43 @@ def test_execute_zonal_statistics(api):
assert api.collections['S2_FAPAR_CLOUDCOVER'].viewingParameters['srs'] == 'EPSG:4326'


def test_create_wmts(api):
def test_create_wmts_040(api):
process_graph = api.load_json("filter_temporal.json")
resp = api.client.post('/openeo/0.4.0/services', content_type='application/json', json={
"custom_param": 45,
post_data = {
"type": 'WMTS',
"process_graph": process_graph,
"custom_param": 45,
"title": "My Service",
"description": "Service description"
}
resp = api.client.post('/openeo/0.4.0/services', content_type='application/json', json=post_data)
assert resp.status_code == 201
assert resp.headers['OpenEO-Identifier'] == 'c63d6c27-c4c2-4160-b7bd-9e32f582daec'
assert resp.headers['Location'].endswith("/services/c63d6c27-c4c2-4160-b7bd-9e32f582daec/service/wmts")

tiled_viewing_service = api.collections["S2"].tiled_viewing_service
assert tiled_viewing_service.call_count == 1
ProcessGraphVisitor.dereference_from_node_arguments(process_graph)
tiled_viewing_service.assert_called_with(
service_type="WMTS",
process_graph=process_graph,
post_data=post_data
)


def test_create_wmts_100(api):
process_graph = api.load_json("filter_temporal.json")
post_data = {
"type": 'WMTS',
"process": {
"process_graph": process_graph,
"id": "filter_temporal_wmts"
},
"custom_param": 45,
"title": "My Service",
"description": "Service description"
})
}
resp = api.client.post('/openeo/1.0.0/services', content_type='application/json', json=post_data)
assert resp.status_code == 201
assert resp.headers['OpenEO-Identifier'] == 'c63d6c27-c4c2-4160-b7bd-9e32f582daec'
assert resp.headers['Location'].endswith("/services/c63d6c27-c4c2-4160-b7bd-9e32f582daec/service/wmts")
Expand All @@ -245,11 +273,13 @@ def test_create_wmts(api):
assert tiled_viewing_service.call_count == 1
ProcessGraphVisitor.dereference_from_node_arguments(process_graph)
tiled_viewing_service.assert_called_with(
custom_param=45, description='Service description', process_graph=process_graph, title='My Service',
type='WMTS'
service_type="WMTS",
process_graph=process_graph,
post_data=post_data
)



def test_read_vector(api):
process_graph = api.load_json(
"read_vector.json",
Expand Down

0 comments on commit 571319d

Please sign in to comment.