Skip to content

Commit b8c647e

Browse files
committed
sandboxjs.py :
- better method to cmp versions - remove tests monkey patch - better condition checking while raising exceptions
1 parent 1ed6bc3 commit b8c647e

File tree

2 files changed

+50
-38
lines changed

2 files changed

+50
-38
lines changed

cwltool/sandboxjs.py

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from io import BytesIO
99

1010
from pkg_resources import resource_stream
11-
from typing import Any, Dict, List, Mapping, Text, Union
11+
from typing import Any, Dict, List, Mapping, Text, Union, Tuple
12+
1213

1314
class JavascriptException(Exception):
1415
pass
@@ -21,45 +22,50 @@ class JavascriptException(Exception):
2122
localdata = threading.local()
2223

2324
have_node_slim = False
24-
25+
# minimum acceptable version of nodejs engine
26+
minimum_node_version_str = '0.10.26'
2527

2628
def check_js_threshold_version(working_alias):
27-
# type: (str) -> bool
28-
""" parse node version: 'v4.2.6\n' -> ['4', '2', '6'],
29-
https://github.com/nodejs/node/blob/master/CHANGELOG.md#nodejs-changelog"""
30-
31-
# try:
32-
v1, v2, v3 = [int(v) for v in subprocess.check_output(
33-
[working_alias, "-v"]).decode('ascii').strip().strip('v').split('.')]
34-
# except Exception as e:
35-
# _logger.debug(str(e))
36-
# _logger.debug("Calling subprocess failed")
37-
# return True
38-
39-
if v1 == 0:
40-
if v2 == 10 and v3 <= 25 or v2 < 10:
41-
return False
42-
return True
29+
# type: (str) -> Tuple[bool, str]
30+
31+
"""Checks if the nodeJS engine version on the system
32+
with the allowed minimum version.
33+
https://github.com/nodejs/node/blob/master/CHANGELOG.md#nodejs-changelog
34+
"""
35+
# parse nodejs version into int Tuple: 'v4.2.6\n' -> [4, 2, 6]
36+
current_version_str = subprocess.check_output(
37+
[working_alias, "-v"]).decode('ascii')
38+
39+
current_version = [int(v) for v in current_version_str.strip().strip('v').split('.')]
40+
minimum_node_version = [int(v) for v in minimum_node_version_str.split('.')]
41+
42+
if current_version >= minimum_node_version:
43+
return True
44+
else:
45+
return False
46+
4347

4448
def new_js_proc():
4549
# type: () -> subprocess.Popen
4650

4751
res = resource_stream(__name__, 'cwlNodeEngine.js')
4852
nodecode = res.read()
4953

54+
required_node_version, docker = (False,)*2
5055
nodejs = None
5156
trynodes = ("nodejs", "node")
52-
working_alias = None
5357
for n in trynodes:
5458
try:
5559
if subprocess.check_output([n, "--eval", "process.stdout.write('t')"]) != "t":
56-
working_alias = n
5760
continue
58-
nodejs = subprocess.Popen([n, "--eval", nodecode],
59-
stdin=subprocess.PIPE,
60-
stdout=subprocess.PIPE,
61-
stderr=subprocess.PIPE)
62-
break
61+
else:
62+
nodejs = subprocess.Popen([n, "--eval", nodecode],
63+
stdin=subprocess.PIPE,
64+
stdout=subprocess.PIPE,
65+
stderr=subprocess.PIPE)
66+
67+
required_node_version = check_js_threshold_version(n)
68+
break
6369
except subprocess.CalledProcessError:
6470
pass
6571
except OSError as e:
@@ -68,15 +74,7 @@ def new_js_proc():
6874
else:
6975
raise
7076

71-
""" check nodejs version, if it is below certain threshold version,
72-
raise Runtime Exception. Such a test won't be required for docker nodejs"""
73-
if nodejs is not None:
74-
if check_js_threshold_version(working_alias) is False:
75-
raise JavascriptException(u"cwltool requires updated version of Node.js engine. "
76-
"Try updating: https://docs.npmjs.com/getting-started/installing-node")
77-
78-
79-
if nodejs is None:
77+
if nodejs is None or nodejs is not None and required_node_version is False:
8078
try:
8179
nodeimg = "node:slim"
8280
global have_node_slim
@@ -91,6 +89,7 @@ def new_js_proc():
9189
"--sig-proxy=true", "--interactive",
9290
"--rm", nodeimg, "node", "--eval", nodecode],
9391
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
92+
docker = True
9493
except OSError as e:
9594
if e.errno == errno.ENOENT:
9695
pass
@@ -99,12 +98,19 @@ def new_js_proc():
9998
except subprocess.CalledProcessError:
10099
pass
101100

101+
# docker failed and nodejs not on system
102102
if nodejs is None:
103103
raise JavascriptException(
104104
u"cwltool requires Node.js engine to evaluate Javascript "
105105
"expressions, but couldn't find it. Tried %s, docker run "
106106
"node:slim" % u", ".join(trynodes))
107107

108+
# docker failed, but nodejs is installed on system but the version is below the required version
109+
if docker is False and required_node_version is False:
110+
raise JavascriptException(
111+
u'cwltool requires minimum v{} version of Node.js engine.'.format(minimum_node_version_str),
112+
u'Try updating: https://docs.npmjs.com/getting-started/installing-node')
113+
108114
return nodejs
109115

110116

@@ -115,7 +121,7 @@ def execjs(js, jslib, timeout=None, debug=False): # type: (Union[Mapping, Text]
115121

116122
nodejs = localdata.proc
117123

118-
fn = u"\"use strict\";\n%s\n(function()%s)()" %\
124+
fn = u"\"use strict\";\n%s\n(function()%s)()" % \
119125
(jslib, js if isinstance(js, basestring) and len(js) > 1 and js[0] == '{' else ("{return (%s);}" % js))
120126

121127
killed = []
@@ -182,7 +188,7 @@ def stdfmt(data): # type: (unicode) -> unicode
182188
nodejs.poll()
183189

184190
if debug:
185-
info = u"returncode was: %s\nscript was:\n%s\nstdout was: %s\nstderr was: %s\n" %\
191+
info = u"returncode was: %s\nscript was:\n%s\nstdout was: %s\nstderr was: %s\n" % \
186192
(nodejs.returncode, fn_linenum(), stdfmt(stdoutdata), stdfmt(stderrdata))
187193
else:
188194
info = stdfmt(stderrdata)

tests/test_js_sandbox.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import unittest
2-
from mock import Mock
2+
from mock import Mock, patch
33

44
# we should modify the subprocess imported from cwltool.sandboxjs
5-
from cwltool.sandboxjs import check_js_threshold_version, subprocess
5+
from cwltool.sandboxjs import check_js_threshold_version, subprocess, minimum_node_version_str
66

77
class Javascript_Sanity_Checks(unittest.TestCase):
88

9+
def setUp(self):
10+
self.check_output = subprocess.check_output
11+
12+
def tearDown(self):
13+
subprocess.check_output = self.check_output
14+
915
def test_node_version(self):
1016
subprocess.check_output = Mock(return_value=b'v0.8.26\n')
1117
self.assertEquals(check_js_threshold_version('node'), False)

0 commit comments

Comments
 (0)