Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(start): validate endpoint parameters (#689) #689

Merged
merged 3 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Check commit message compliance of the pull request
if: github.event_name == 'pull_request'
run: |
./run-tests.sh --check-commitlint ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.number }}
./run-tests.sh --check-commitlint ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.number }}
lint-shellcheck:
runs-on: ubuntu-20.04
Expand Down
4 changes: 4 additions & 0 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3198,15 +3198,19 @@
"schema": {
"properties": {
"input_parameters": {
"description": "Optional. Additional input parameters that override the ones from the workflow specification.",
"type": "object"
},
"operational_options": {
"description": "Optional. Additional operational options for workflow execution.",
"type": "object"
},
"reana_specification": {
"description": "Optional. Replace the original workflow specification with the given one. Only considered when restarting a workflow.",
"type": "object"
},
"restart": {
"description": "Optional. If true, restart the given workflow.",
"type": "boolean"
}
},
Expand Down
51 changes: 35 additions & 16 deletions reana_server/rest/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,8 @@ def get_workflow_specification(workflow_id_or_name, user): # noqa
jsonify(
{
"specification": workflow.reana_specification,
"parameters": workflow.input_parameters,
# `input_parameters` can be null, if so return an empty dict
"parameters": workflow.input_parameters or {},
}
),
200,
Expand Down Expand Up @@ -1132,8 +1133,16 @@ def get_workflow_status(workflow_id_or_name, user): # noqa

@blueprint.route("/workflows/<workflow_id_or_name>/start", methods=["POST"])
@signin_required()
@use_kwargs(
{
"operational_options": fields.Dict(location="json"),
"input_parameters": fields.Dict(location="json"),
"restart": fields.Boolean(location="json"),
"reana_specification": fields.Raw(location="json"),
}
)
@check_quota
def start_workflow(workflow_id_or_name, user): # noqa
def start_workflow(workflow_id_or_name, user, **parameters): # noqa
r"""Start workflow.
---
post:
Expand Down Expand Up @@ -1166,12 +1175,20 @@ def start_workflow(workflow_id_or_name, user): # noqa
type: object
properties:
operational_options:
type: object
reana_specification:
description: Optional. Additional operational options for workflow execution.
type: object
input_parameters:
description: >-
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See description verbiage comments above.

Optional. Additional input parameters that override the ones from
the workflow specification.
type: object
reana_specification:
description: >-
Optional. Replace the original workflow specification with the given one.
Only considered when restarting a workflow.
type: object
restart:
description: Optional. If true, restart the given workflow.
type: boolean
responses:
200:
Expand Down Expand Up @@ -1285,32 +1302,33 @@ def start_workflow(workflow_id_or_name, user): # noqa
"message": "Status resume is not supported yet."
}
"""

operational_options = parameters.get("operational_options", {})
input_parameters = parameters.get("input_parameters", {})
restart = parameters.get("restart", False)
reana_specification = parameters.get("reana_specification")

try:
if not workflow_id_or_name:
raise ValueError("workflow_id_or_name is not supplied")
parameters = request.json if request.is_json else {}

workflow = _get_workflow_with_uuid_or_name(workflow_id_or_name, str(user.id_))
operational_options = parameters.get("operational_options", {})
operational_options = validate_operational_options(
workflow.type_, operational_options
)

restart_type = None
if "restart" in parameters:
if restart:
if workflow.status not in [RunStatus.finished, RunStatus.failed]:
raise ValueError("Only finished or failed workflows can be restarted.")
if workflow.workspace_has_pending_retention_rules():
raise ValueError(
"The workflow cannot be restarted because some retention rules are "
"currently being applied to the workspace. Please retry later."
)
restart_type = (
parameters.get("reana_specification", {})
.get("workflow", {})
.get("type", None)
)
workflow = clone_workflow(
workflow, parameters.get("reana_specification", None), restart_type
)
if reana_specification:
restart_type = reana_specification.get("workflow", {}).get("type", None)
workflow = clone_workflow(workflow, reana_specification, restart_type)
elif workflow.status != RunStatus.created:
raise ValueError(
"Workflow {} is already {} and cannot be started "
Expand All @@ -1319,11 +1337,12 @@ def start_workflow(workflow_id_or_name, user): # noqa
if "yadage" in (workflow.type_, restart_type):
_load_and_save_yadage_spec(workflow, operational_options)

input_parameters = parameters.get("input_parameters", {})
validate_workflow(
workflow.reana_specification, input_parameters=input_parameters
)

# when starting the workflow, the scheduler will call RWC's `set_workflow_status`
# with the given `parameters`
publish_workflow_submission(workflow, user.id_, parameters)
response = {
"message": "Workflow submitted.",
Expand Down
18 changes: 14 additions & 4 deletions run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,25 @@ check_commitlint () {
npx commitlint --from="$from" --to="$to"
found=0
while IFS= read -r line; do
if echo "$line" | grep -qP "\(\#$pr\)$"; then
commit_hash=$(echo "$line" | cut -d ' ' -f 1)
Copy link
Member

@tiborsimko tiborsimko Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the commit message saying in a negatively-worded tense:

ci(commitlint): do not check merge commit's ancestors 

What about putting a positively-worded message:

ci(commitlint): improve checking of merge commits

As we did in several other PRs such as merge-0.9-to-master ones?

commit_title=$(echo "$line" | cut -d ' ' -f 2-)
commit_number_of_parents=$(git rev-list --parents "$commit_hash" -n1 | awk '{print NF-1}')
if [ "$commit_number_of_parents" -gt 1 ]; then
if echo "$commit_title" | grep -qP "^chore\(.*\): merge "; then
break
else
echo "✖ Merge commits are not allowed in feature branches: $commit_title"
found=1
fi
elif echo "$commit_title" | grep -qP "^chore\(.*\): release"; then
true
elif echo "$line" | grep -qP "^chore\(.*\): release"; then
elif echo "$commit_title" | grep -qP "\(\#$pr\)$"; then
true
else
echo "✖ Headline does not end by '(#$pr)' PR number: $line"
echo "✖ Headline does not end by '(#$pr)' PR number: $commit_title"
found=1
fi
done < <(git log "$from..$to" --format="%s")
done < <(git log "$from..$to" --format="%H %s")
if [ $found -gt 0 ]; then
exit 1
fi
Expand Down
2 changes: 1 addition & 1 deletion tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def test_restart_workflow_validates_specification(
workflow_specification["workflow"]["type"] = "unknown"
body = {
"reana_specification": workflow_specification,
"restart": "can be anything here doesnt matter",
"restart": True,
}
res = client.post(
url_for("workflows.start_workflow", workflow_id_or_name="test"),
Expand Down
Loading