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

validate: add validate-sections to validate misspelled directives or directives in reana.yaml #564

Merged
merged 1 commit into from
Oct 1, 2021

Conversation

marcdiazsan
Copy link
Contributor

Closes #562

@marcdiazsan marcdiazsan self-assigned this Sep 27, 2021
@codecov-commenter
Copy link

codecov-commenter commented Sep 27, 2021

Codecov Report

Merging #564 (fda2ad9) into master (40fc775) will decrease coverage by 0.05%.
The diff coverage is 20.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #564      +/-   ##
==========================================
- Coverage   58.20%   58.14%   -0.06%     
==========================================
  Files          20       20              
  Lines        2395     2399       +4     
==========================================
+ Hits         1394     1395       +1     
- Misses       1001     1004       +3     
Impacted Files Coverage Δ
reana_client/utils.py 67.00% <20.00%> (-0.88%) ⬇️

@@ -123,7 +123,11 @@ def _prepare_kwargs(reana_yaml):
try:
with open(filepath) as f:
reana_yaml = yaml.load(f.read(), Loader=yaml.FullLoader)

try:
_validate_sections(reana_yaml)
Copy link
Member

Choose a reason for hiding this comment

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

Instead of implementing our own validation, I think it's simpler and more scalable to enrich the reana.yaml JSON Schema and define a more strict structure. Then we can catch the errors and display them properly.
Check the JSON Schema docs to see how to restrict to certain properties and so on: https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties

Related issues:

reana_client/utils.py Outdated Show resolved Hide resolved
@@ -123,7 +124,6 @@ def _prepare_kwargs(reana_yaml):
try:
with open(filepath) as f:
reana_yaml = yaml.load(f.read(), Loader=yaml.FullLoader)

workflow_type = reana_yaml["workflow"]["type"]
Copy link
Member

@mvidalgarcia mvidalgarcia Sep 29, 2021

Choose a reason for hiding this comment

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

E.g. If we have typ instead of type we'll have an exception here without even reaching the JSON Schema validation (_validate_reana_yaml(reana_yaml)). Perhaps we can move the validation to be performed before and detect schema problems earlier?

diff --git a/reana.yaml b/reana.yaml
index 9fcfa12..4cf462c 100644
--- a/reana.yaml
+++ b/reana.yaml
@@ -11,7 +11,7 @@ inputs:
     year_min: 1500
     year_max: 2012
 workflow:
-  type: serial
+  typ: serial
   specification:
     steps:
       - environment: 'reanahub/reana-env-jupyter:2.0.0'
$ reana-client validate    
==> ERROR: Something went wrong when trying to validate ~/code/reanahub/reana-demo-worldpopulation/reana.yaml

I have no hints on what is wrong.

Copy link
Member

@mvidalgarcia mvidalgarcia Sep 29, 2021

Choose a reason for hiding this comment

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

Following the IRL conversation, I meant something like this:

diff --git a/reana_client/utils.py b/reana_client/utils.py
index 5bc4312..e840648 100644
--- a/reana_client/utils.py
+++ b/reana_client/utils.py
@@ -124,7 +124,16 @@ def load_reana_spec(
     try:
         with open(filepath) as f:
             reana_yaml = yaml.load(f.read(), Loader=yaml.FullLoader)
-        workflow_type = reana_yaml["workflow"]["type"]
+        workflow_type = reana_yaml["workflow"].get("type")
+        if not skip_validation:
+            display_message(
+                "Verifying REANA specification file... {filepath}".format(
+                    filepath=filepath
+                ),
+                msg_type="info",
+            )
+            _validate_reana_yaml(reana_yaml)
+            validate_parameters(workflow_type, reana_yaml)
         reana_yaml["workflow"]["specification"] = load_workflow_spec(
             workflow_type,
             reana_yaml["workflow"].get("file"),
@@ -139,16 +148,6 @@ def load_reana_spec(
                     f, Loader=yaml.FullLoader
                 )
 
-        if not skip_validation:
-            display_message(
-                "Verifying REANA specification file... {filepath}".format(
-                    filepath=filepath
-                ),
-                msg_type="info",
-            )
-            _validate_reana_yaml(reana_yaml)
-            validate_parameters(workflow_type, reana_yaml)
-
         if not skip_validate_environments:
             display_message(
                 "Verifying environments in REANA specification file...",

So then the output is more informative:

$ reana-client validate 
==> Verifying REANA specification file... /Users/marco/code/reanahub/reana-demo-worldpopulation/reana.yaml
==> ERROR: /Users/marco/code/reanahub/reana-demo-worldpopulation/reana.yaml is not a valid REANA specification:
==> ERROR:  The `reana.yaml` directive "typ" is not valid.

Note. Beware possible side effects, I haven't tested it deeply.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree to move the _validate_reana_yaml but validate_parameters would need to load the specification file. I would rather separate them

Comment on lines 208 to 212
invalid_section = (
".".join(e.path[1], e.message.split("'")[1])
if len(e.path) > 1
else e.message.split("'")[1]
)
Copy link
Member

Choose a reason for hiding this comment

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

For simplicity, perhaps we can just use e.message here? Unless I'm missing something, the messages are quite descriptive:

"Additional properties are not allowed ('typ' was unexpected)"

Comment on lines 207 to 209
raise REANAValidationError(
'==> ERROR: The `reana.yaml` is not valid: "{0}".'.format(e.message)
)
Copy link
Member

Choose a reason for hiding this comment

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

Couple of things:

  • It'd be nice to keep the same colors for the error messages and rely on display_message() instead of appending ourselves the "==> ERROR:" prefix
  • Error code is 0 when failing

image

Comment on lines +103 to +110
"oneOf": [
{
"required": ["type","file"]
},
{
"required": ["type","specification"]
}
]
Copy link
Member

Choose a reason for hiding this comment

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

Nice! 👍

Update validate schema to restrict the directives allowed and to be consisten with the documentation

Closes reanahub#562, Closes reanahub#404
Copy link
Member

@mvidalgarcia mvidalgarcia left a comment

Choose a reason for hiding this comment

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

👍

@mvidalgarcia mvidalgarcia merged commit 811d1a0 into reanahub:master Oct 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

validate: catch problems with misspelled inputs.files and similar directives
3 participants