Skip to content

Commit

Permalink
partial support of CWL for single app process (relates to #56)
Browse files Browse the repository at this point in the history
  • Loading branch information
fmigneault committed Jun 9, 2022
1 parent 2e3e016 commit 64df036
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ Changes:
``application/ogcapppkg+yaml`` for the |ogc-app-pkg|_ schema, or using ``application/cwl+yaml`` for
a `CWL`-only definition. The definition will be loaded and converted to ``JSON`` for schema validation. Otherwise,
``JSON`` contents is assumed to be directly provided in the request payload for validation as previously accomplished.
- Add partial support of `CWL` with ``$graph`` representation for the special case where the graph is composed of a list
of exactly one `Application Package`. Multi/nested-`CWL` definitions are **NOT** supported
(relates to `#56 <https://github.com/crim-ca/weaver/issues/56>`_).

Fixes:
------
Expand Down
17 changes: 12 additions & 5 deletions weaver/processes/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

LOGGER = logging.getLogger(__name__)
if TYPE_CHECKING:
from typing import Any, List, Optional, Tuple, Union
from typing import List, Optional, Tuple, Union

from pyramid.request import Request

Expand Down Expand Up @@ -143,7 +143,6 @@ def _check_deploy(payload):
"""
Validate minimum deploy payload field requirements with exception handling.
"""
# FIXME: handle colander invalid directly in tween (https://github.com/crim-ca/weaver/issues/112)
message = "Process deployment definition is invalid."
try:
results = sd.Deploy().deserialize(payload)
Expand Down Expand Up @@ -207,6 +206,7 @@ def _check_deploy(payload):
generate_diff(p_exec_unit, r_exec_unit, val_name="original payload", ref_name="parsed result")
)
return results
# FIXME: handle colander invalid directly in tween (https://github.com/crim-ca/weaver/issues/112)
except colander.Invalid as exc:
LOGGER.debug("Failed deploy body schema validation:\n%s", exc)
raise HTTPBadRequest(json={
Expand Down Expand Up @@ -287,6 +287,7 @@ def _load_payload(payload, content_type):
return payload


# FIXME: supported nested and $graph multi-deployment (https://github.com/crim-ca/weaver/issues/56)
def deploy_process_from_payload(payload, container, overwrite=False):
# type: (Union[JSON, str], Union[AnySettingsContainer, AnyRequestType], bool) -> HTTPException
"""
Expand All @@ -312,7 +313,7 @@ def deploy_process_from_payload(payload, container, overwrite=False):
payload = _check_deploy(payload)

# validate identifier naming for unsupported characters
process_description = payload.get("processDescription")
process_description = payload.get("processDescription", {}) # empty possible if CWL directly passed
process_info = process_description.get("process", process_description)
process_href = process_description.pop("href", None)

Expand All @@ -335,9 +336,14 @@ def deploy_process_from_payload(payload, container, overwrite=False):
package = None
reference = content.get("href")
found = isinstance(reference, str)
elif c_type in (ContentType.ANY_CWL + [ContentType.APP_JSON]) and "cwlVersion" in payload:
package = payload
elif c_type in (list(ContentType.ANY_CWL) + [ContentType.APP_JSON]) and "cwlVersion" in payload:
process_info = {}
package = payload
if "$graph" in package and isinstance(package["$graph"], list) and len(package["$graph"]) == 1:
# consider package as if provided in non-graph representation
# must preserve top level fields (e.g.: 'cwlVersion') and nested graph item
package.update(package.pop("$graph")[0])
found = True
else: # ogc-apppkg type, but no explicit check since used by default (backward compat)
if deployment_profile_name: # optional hint
allowed_profile_suffix = [ProcessType.APPLICATION, ProcessType.WORKFLOW]
Expand All @@ -363,6 +369,7 @@ def deploy_process_from_payload(payload, container, overwrite=False):
"ProcessDescription.href",
"ProcessDescription.owsContext.content.href",
"executionUnit[*].(unit|href)",
"{ <CWL> }",
]
raise HTTPBadRequest(
f"Missing one of required parameters {params} to obtain package/process definition or reference."
Expand Down
2 changes: 1 addition & 1 deletion weaver/wps_restapi/processes/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def add_local_process(request):
"""
Register a local process.
"""
return deploy_process_from_payload(request.body, request)
return deploy_process_from_payload(request.text, request) # use text to allow parsing as JSON or YAML


@sd.process_service.get(tags=[sd.TAG_PROCESSES, sd.TAG_DESCRIBEPROCESS], renderer=OutputFormat.JSON,
Expand Down
22 changes: 15 additions & 7 deletions weaver/wps_restapi/swagger_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import duration
import yaml
from colander import DateTime, Email, Money, OneOf, Range, Regex, drop, null, required
from colander import DateTime, Email, Length, Money, OneOf, Range, Regex, drop, null, required
from dateutil import parser as date_parser

from weaver import __meta__
Expand Down Expand Up @@ -4149,15 +4149,19 @@ class CWLGraphList(ExtendedSequenceSchema):
cwl = CWLGraphItem()


# FIXME: supported nested and $graph multi-deployment (https://github.com/crim-ca/weaver/issues/56)
class CWLGraphBase(ExtendedMappingSchema):
graph = CWLGraphList(
name="$graph", description=(
"Graph definition that combines one or many CWL application packages within a single payload. "
"If an single application is given (list of one item), it will be deployed as normal CWL by itself. "
"If multiple applications are defined, the first MUST be the top-most Workflow process. "
"Other items deployment will be performed, and the full deployment will be persisted only if all are "
"valid. The resulting Workflow will be registered as a package by itself (i.e: not as a graph)."
)
"Graph definition that defines *exactly one* CWL application package represented as list. "
"Multiple definitions simultaneously deployed is NOT supported at the moment."
# "Graph definition that combines one or many CWL application packages within a single payload. "
# "If an single application is given (list of one item), it will be deployed as normal CWL by itself. "
# "If multiple applications are defined, the first MUST be the top-most Workflow process. "
# "Deployment of other items will be performed, and the full deployment will be persisted only if all are "
# "valid. The resulting Workflow will be registered as a package by itself (i.e: not as a graph)."
),
validator=Length(min=1, max=1)
)


Expand All @@ -4170,6 +4174,10 @@ class DeployCWL(NotKeywordSchema, CWL):
CWLGraphBase()
]
id = CWLIdentifier() # required in this case
inputs = CWLInputsDefinition(
missing=drop, # empty definition permitted during deployment
description="All inputs available to the Application Package.",
)


class Deploy(OneOfKeywordSchema):
Expand Down

0 comments on commit 64df036

Please sign in to comment.