From 1efd2c73580a879f193f125a433044432ca99d6c Mon Sep 17 00:00:00 2001
From: Charlotte Hausman <chausman@nrao.edu>
Date: Wed, 10 Nov 2021 13:04:57 -0500
Subject: [PATCH] Create new REST endpoints for returning capability versions

---
 services/capability/capability/routes.py      | 28 ++++++-
 .../capability/views/capability_version.py    | 81 +++++++++++++++++++
 .../capability/test/test_capability_server.py |  3 +
 3 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/services/capability/capability/routes.py b/services/capability/capability/routes.py
index 974b5cc71..092d0d0fa 100644
--- a/services/capability/capability/routes.py
+++ b/services/capability/capability/routes.py
@@ -117,14 +117,38 @@ def capability_version_routes(config: Configurator):
     """
     request_url = "capability/request/{capability_request_id}/version"
     # GET
+    config.add_route(
+        name="view_all_versions",
+        pattern=f"{request_url}s",
+        request_method="GET",
+    )
     config.add_route(
         name="view_latest_version",
         pattern=f"{request_url}/latest",
         request_method="GET",
     )
+    config.add_route(
+        name="view_specific_version",
+        pattern="capability/request/{capability_request_id}/version/{version_id}",
+        request_method="GET",
+    )
+
     # POST
-    config.add_route(name="create_capability_version", pattern=f"{request_url}/create", request_method="POST")
-    config.add_route(name="add_version_file", pattern=f"{request_url}/file/add", request_method="POST")
+    config.add_route(
+        name="create_capability_version",
+        pattern=f"{request_url}/create",
+        request_method="POST",
+    )
+    config.add_route(
+        name="submit_capability_version",
+        pattern="capability/request/{capability_request_id}/version/{version_id}/submit",
+        request_method="POST",
+    )
+    config.add_route(
+        name="add_version_file",
+        pattern=f"{request_url}/file/add",
+        request_method="POST",
+    )
 
     # PUT
     config.add_route(
diff --git a/services/capability/capability/views/capability_version.py b/services/capability/capability/views/capability_version.py
index 1a611f06c..3f302dcb3 100644
--- a/services/capability/capability/views/capability_version.py
+++ b/services/capability/capability/views/capability_version.py
@@ -27,6 +27,31 @@ from pyramid.response import Response
 from pyramid.view import view_config
 
 
+@view_config(route_name="view_all_versions", renderer="json")
+def view_all_versions(request: Request):
+    """
+    Pyramid view that accepts a request to view all versions of a capability request
+    URL: capability/request/{capability_request_id}/versions
+
+    :param request: GET request
+    :return: 200 OK response with JSON-formatted info of latest version of request with given ID
+        or 404 response (HTTPNotFound) if capability request with given ID does not exist
+        or 412 response (HTTPPreconditionFailed) if capability request with given ID has no versions
+    """
+    capability_request = request.capability_info.lookup_capability_request(request.matchdict["capability_request_id"])
+    if capability_request:
+        if capability_request.versions:
+            return capability_request.versions
+        else:
+            no_versions_msg = (
+                f"Capability request with ID {request.matchdict['capability_request_id']} has no versions."
+            )
+            return HTTPPreconditionFailed(no_versions_msg)
+    else:
+        not_found_msg = (f"Capability request with ID {request.matchdict['capability_request_id']} not found.",)
+        return HTTPNotFound(detail=not_found_msg)
+
+
 @view_config(route_name="view_latest_version", renderer="json")
 def view_latest_version(request: Request) -> Response:
     """
@@ -58,6 +83,36 @@ def view_latest_version(request: Request) -> Response:
         return HTTPNotFound(detail=not_found_msg)
 
 
+@view_config(route_name="view_specific_version", renderer="json")
+def view_specific_version(request: Request) -> Response:
+    """
+    Pyramid view that accepts a request to get a specific version of a capability request
+    URL: capability/request/{capability_request_id}/version/{version_id}
+
+    :param request: GET request
+    :return: 200 OK response with JSON-formatted info of latest version of request with given ID
+        or 404 response (HTTPNotFound) if capability request with given ID does not exist
+        or 412 response (HTTPPreconditionFailed) if capability request with given ID has no versions
+    """
+
+    capability_request_id = request.matchdict["capability_request_id"]
+    version_id = request.matchdict["version_id"]
+
+    capability_request = request.capability_info.lookup_capability_request(capability_request_id)
+    if capability_request:
+        version = capability_request.versions[int(version_id) - 1]
+        if version:
+            return version
+        else:
+            no_versions_msg = (
+                f"Capability request with ID {request.matchdict['capability_request_id']} has no versions."
+            )
+            return HTTPPreconditionFailed(no_versions_msg)
+    else:
+        not_found_msg = (f"Capability request with ID {request.matchdict['capability_request_id']} not found.",)
+        return HTTPNotFound(detail=not_found_msg)
+
+
 @view_config(route_name="create_capability_version", renderer="json")
 def create_capability_version(request: Request) -> Response:
     """
@@ -88,6 +143,32 @@ def create_capability_version(request: Request) -> Response:
         return Response(json_body=new_capability_version.__json__())
 
 
+@view_config(route_name="submit_capability_version", renderer="json")
+def submit_capability_version(request: Request) -> Response:
+    """
+    Pyramid view that accepts a request to submit a capability version for execution
+    URL: capability/request/{capability_request_id}/version/{version_id}/submit
+
+    :param request: POST request, expecting JSON parameter "parameters"
+    :return: 200 OK response with JSON-formatted info of newly created capability request
+        or 400 response (HTTPBadRequest) if expected parameters not given
+        or 412 response (HTTPPreconditionFailed) if capability request with given id does not exist
+    """
+
+    capability_request_id = request.matchdict["capability_request_id"]
+    version_id = request.matchdict["version_id"]
+
+    capability_request = request.capability_info.lookup_capability_request(capability_request_id)
+
+    if not capability_request:
+        # Capability request not found
+        does_not_exist_msg = f"Capability request with ID {capability_request_id} does not exist. Cannot submit."
+        return HTTPPreconditionFailed(detail=does_not_exist_msg)
+
+    execution = request.capability_launcher.launch_capability(capability_request, version_id)
+    return Response(json_body=execution.__json__())
+
+
 @view_config(route_name="add_version_file", renderer="json")
 def add_version_file(request: Request) -> Response:
     """
diff --git a/services/capability/test/test_capability_server.py b/services/capability/test/test_capability_server.py
index 92e219770..9f75a1199 100644
--- a/services/capability/test/test_capability_server.py
+++ b/services/capability/test/test_capability_server.py
@@ -46,8 +46,11 @@ def capability_routes() -> RouteList:
         "submit_capability_request",
         "cancel_capability_request",
         "delete_capability_request",
+        "view_all_versions",
         "view_latest_version",
+        "view_specific_version",
         "create_capability_version",
+        "submit_capability_version",
         "add_version_file",
         "add_file_to_latest",
         "create_version_from_previous_execution_script",
-- 
GitLab