support large arguments (#3)
diff --git a/core/actionProxy/actionproxy.py b/core/actionProxy/actionproxy.py
index 8e43576..bbe9902 100644
--- a/core/actionProxy/actionproxy.py
+++ b/core/actionProxy/actionproxy.py
@@ -47,10 +47,11 @@
# @param source the path where the source code will be located (if any)
# @param binary the path where the binary will be located (may be the
# same as source code path)
- def __init__(self, source=None, binary=None):
+ def __init__(self, source=None, binary=None, zipdest=None):
defaultBinary = '/action/exec'
self.source = source if source else defaultBinary
self.binary = binary if binary else defaultBinary
+ self.zipdest = zipdest if zipdest else os.path.dirname(self.source)
def preinit(self):
return
@@ -127,18 +128,29 @@
try:
input = json.dumps(args)
- p = subprocess.Popen(
- [self.binary, input],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- env=env)
+ if len(input) > 131071: # MAX_ARG_STRLEN (131071) linux/binfmts.h
+ # pass argument via stdin
+ p = subprocess.Popen(
+ [self.binary],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env)
+ else:
+ # pass argument via stdin and command parameter
+ p = subprocess.Popen(
+ [self.binary, input],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env)
+ # run the process and wait until it completes.
+ # stdout/stderr will always be set because we passed PIPEs to Popen
+ (o, e) = p.communicate(input=input.encode())
+
except Exception as e:
return error(e)
- # run the process and wait until it completes.
- # stdout/stderr will always be set because we passed PIPEs to Popen
- (o, e) = p.communicate()
-
# stdout/stderr may be either text or bytes, depending on Python
# version, so if bytes, decode to text. Note that in Python 2
# a string will match both types; so also skip decoding in that case
@@ -182,7 +194,7 @@
bytes = base64.b64decode(message['code'])
bytes = io.BytesIO(bytes)
archive = zipfile.ZipFile(bytes)
- archive.extractall(os.path.dirname(self.source))
+ archive.extractall(self.zipdest)
archive.close()
return True
except Exception as e:
diff --git a/core/actionProxy/stub.sh b/core/actionProxy/stub.sh
index 842d00a..420b7fd 100644
--- a/core/actionProxy/stub.sh
+++ b/core/actionProxy/stub.sh
@@ -2,8 +2,18 @@
echo \
'This is a stub action that should be replaced with user code (e.g., script or compatible binary).
-The input to the action is received as an argument from the command line.
+The input to the action is received from stdin, and up to a size of MAX_ARG_STRLEN (131071) also as an argument from the command line.
Actions may log to stdout or stderr. By convention, the last line of output must
be a stringified JSON object which represents the result of the action.'
-echo '{ "error": "This is a stub action. Replace it with custom logic." }'
\ No newline at end of file
+# getting arguments from command line
+# only arguments up to a size of MAX_ARG_STRLEN (else empty) supported
+echo 'command line argument: '$1
+echo 'command line argument length: '${#1}
+
+# getting arguments from stdin
+read inputstring
+echo 'stdin input length: '${#inputstring}
+
+# last line of output = ation result
+echo '{ "error": "This is a stub action. Replace it with custom logic." }'
diff --git a/tests/src/test/scala/actionContainers/ActionProxyContainerTests.scala b/tests/src/test/scala/actionContainers/ActionProxyContainerTests.scala
index bcf5602..80109bc 100644
--- a/tests/src/test/scala/actionContainers/ActionProxyContainerTests.scala
+++ b/tests/src/test/scala/actionContainers/ActionProxyContainerTests.scala
@@ -343,4 +343,23 @@
}
}
}
+
+ it should "receive a large (1MB) argument" in {
+ withActionContainer() { c =>
+ val code = """
+ |#!/bin/bash
+ | read inputstring
+ | echo $inputstring
+ |
+ """.stripMargin.trim
+
+ val (initCode, initRes) = c.init(initPayload(code))
+ initCode should be(200)
+
+ val arg = JsObject("arg" -> JsString(("a" * 1048561)))
+ val (_, runRes) = c.run(runPayload(arg))
+ runRes.get shouldBe arg
+ }
+ }
+
}