Introduce strict shell command option.

Newer tool formats (CWL and YAML just enable this by default), but XML tools can add a strict="true" to the command block to force "set -e" handling on the shell part of tool execution.

Run the framework tests verifying the new and older default behavior using the following commands:

```
./run_tests.sh -framework -id strict_shell_default_off
./run_tests.sh -framework -id strict_shell
```
This commit is contained in:
John Chilton
2016-02-22 09:58:43 +00:00
parent 45ac2de349
commit d020522650
11 changed files with 82 additions and 1 deletions
+4
View File
@@ -793,6 +793,10 @@ class JobWrapper( object ):
def shell(self):
return self.job_destination.shell or getattr(self.app.config, 'default_job_shell', DEFAULT_JOB_SHELL)
@property
def strict_shell(self):
return self.tool.strict_shell
@property
def commands_in_new_shell(self):
return self.app.config.commands_in_new_shell
+9 -1
View File
@@ -87,7 +87,15 @@ def __externalize_commands(job_wrapper, shell, commands_builder, remote_command_
integrity_injection = ""
if check_script_integrity(config):
integrity_injection = INTEGRITY_INJECTION
script_contents = u"#!%s\n%s%s" % (shell, integrity_injection, tool_commands)
set_e = ""
if job_wrapper.strict_shell:
set_e = "set -e\n"
script_contents = u"#!%s\n%s%s%s" % (
shell,
integrity_injection,
set_e,
tool_commands
)
write_script(local_container_script, script_contents, config)
commands = local_container_script
if 'working_directory' in remote_command_params:
+3
View File
@@ -562,6 +562,9 @@ class Tool( object, Dictifiable ):
# Parse result handling for tool exit codes and stdout/stderr messages:
self.parse_stdio( tool_source )
self.strict_shell = tool_source.parse_strict_shell()
# Any extra generated config files for the tool
self.__parse_config_files(tool_source)
# Action
+3
View File
@@ -61,6 +61,9 @@ class CwlToolSource(ToolSource):
def parse_help(self):
return ""
def parse_strict_shell(self):
return True
def parse_stdio(self):
# TODO: remove duplication with YAML
from galaxy.jobs.error_level import StdioErrorLevel
+6
View File
@@ -139,6 +139,12 @@ class ToolSource(object):
dictionaries for use by Tool.
"""
@abstractmethod
def parse_strict_shell(self):
""" Return True if tool commands should be executed with
set -e.
"""
@abstractmethod
def parse_stdio(self):
""" Builds lists of ToolStdioExitCode and ToolStdioRegex objects
+7
View File
@@ -281,6 +281,13 @@ class XmlToolSource(ToolSource):
parser = StdioParser(self.root)
return parser.stdio_exit_codes, parser.stdio_regexes
def parse_strict_shell(self):
command_el = self._command_el
if command_el is not None:
return string_as_bool(command_el.get("strict", "False"))
else:
return False
def parse_help(self):
help_elem = self.root.find( 'help' )
return help_elem.text if help_elem is not None else None
+4
View File
@@ -64,6 +64,10 @@ class YamlToolSource(ToolSource):
page_source = YamlPageSource(self.root_dict.get("inputs", {}))
return PagesSource([page_source])
def parse_strict_shell(self):
# TODO: Add ability to disable this.
return True
def parse_stdio(self):
return error_on_exit_code()
@@ -23,6 +23,8 @@
<tool file="metadata.xml" />
<tool file="metadata_bam.xml" />
<tool file="metadata_bcf.xml" />
<tool file="strict_shell.xml" />
<tool file="strict_shell_default_off.xml" />
<tool file="detect_errors_aggressive.xml" />
<tool file="md5sum.xml" />
<!--
+23
View File
@@ -0,0 +1,23 @@
<tool id="strict_shell" name="strict_shell" version="1.0.0">
<command strict="true" detect_errors="exit_code">
echo "Hello" > $out_file1
; sh -c "exit $exit_code"
; sh -c "exit 0"
</command>
<inputs>
<param name="exit_code" type="integer" value="0" label="exit code"/>
</inputs>
<outputs>
<data name="out_file1" />
</outputs>
<tests>
<test expect_exit_code="0" expect_failure="false">
<param name="exit_code" value="0" />
</test>
<test expect_exit_code="1" expect_failure="true">
<param name="exit_code" value="1" />
</test>
</tests>
<help>
</help>
</tool>
@@ -0,0 +1,20 @@
<tool id="strict_shell_default_off" name="strict_shell_default_off" version="1.0.0">
<command detect_errors="exit_code">
echo "Hello" > $out_file1
; sh -c "exit $exit_code"
; sh -c "exit 0"
</command>
<inputs>
<param name="exit_code" type="integer" value="0" label="exit code"/>
</inputs>
<outputs>
<data name="out_file1" />
</outputs>
<tests>
<test expect_exit_code="0" expect_failure="false">
<param name="exit_code" value="1" />
</test>
</tests>
<help>
</help>
</tool>
+1
View File
@@ -155,6 +155,7 @@ class TestCommandFactory(TestCase):
class MockJobWrapper(object):
def __init__(self, job_dir):
self.strict_shell = False
self.write_version_cmd = None
self.command_line = MOCK_COMMAND_LINE
self.dependency_shell_commands = []