move global variables initialized to init (#54)
* move global variables initialized to init
* modify two test cases to initialize the return status
* modifiy python3Action Dockerfile and Tests
diff --git a/core/python3AiAction/Dockerfile b/core/python3AiAction/Dockerfile
index b815b9e..be7e7f7 100644
--- a/core/python3AiAction/Dockerfile
+++ b/core/python3AiAction/Dockerfile
@@ -56,6 +56,6 @@
ADD https://raw.githubusercontent.com/apache/incubator-openwhisk-runtime-docker/dockerskeleton%401.3.3/core/actionProxy/actionproxy.py /actionProxy/actionproxy.py
RUN mkdir -p /pythonAction
-ADD https://raw.githubusercontent.com/apache/incubator-openwhisk-runtime-python/3%401.0.3/core/pythonAction/pythonrunner.py /pythonAction/pythonrunner.py
+COPY pythonrunner.py /pythonAction/pythonrunner.py
CMD ["/bin/bash", "-c", "cd /pythonAction && python -u pythonrunner.py"]
diff --git a/core/python3AiAction/pythonrunner.py b/core/python3AiAction/pythonrunner.py
new file mode 100644
index 0000000..70df3fc
--- /dev/null
+++ b/core/python3AiAction/pythonrunner.py
@@ -0,0 +1,100 @@
+"""Executable Python script for running Python actions.
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+"""
+
+import os
+import sys
+import codecs
+import traceback
+sys.path.append('../actionProxy')
+from actionproxy import ActionRunner, main, setRunner
+
+
+class PythonRunner(ActionRunner):
+
+ def __init__(self):
+ ActionRunner.__init__(self, '/action/__main__.py')
+ self.fn = None
+ self.mainFn = 'main'
+ self.global_context = {}
+
+ def initCodeFromString(self, message):
+ # do nothing, defer to build step
+ return True
+
+ def build(self, message):
+ binary = message['binary'] if 'binary' in message else False
+ if not binary:
+ code = message['code']
+ filename = 'action'
+ elif os.path.isfile(self.source):
+ with codecs.open(self.source, 'r', 'utf-8') as m:
+ code = m.read()
+ workdir = os.path.dirname(self.source)
+ sys.path.insert(0, workdir)
+ os.chdir(workdir)
+ else:
+ sys.stderr.write('Zip file does not include ' + os.path.basename(self.source) + '\n')
+ return False
+
+ try:
+ filename = os.path.basename(self.source)
+ self.fn = compile(code, filename=filename, mode='exec')
+ if 'main' in message:
+ self.mainFn = message['main']
+
+ # if the directory 'virtualenv' is extracted out of a zip file
+ path_to_virtualenv = os.path.dirname(self.source) + '/virtualenv'
+ if os.path.isdir(path_to_virtualenv):
+ # activate the virtualenv using activate_this.py contained in the virtualenv
+ activate_this_file = path_to_virtualenv + '/bin/activate_this.py'
+ if os.path.exists(activate_this_file):
+ with open(activate_this_file) as f:
+ code = compile(f.read(), activate_this_file, 'exec')
+ exec(code, dict(__file__=activate_this_file))
+ else:
+ sys.stderr.write('Invalid virtualenv. Zip file does not include /virtualenv/bin/' + os.path.basename(activate_this_file) + '\n')
+ return False
+ exec(self.fn, self.global_context)
+ return True
+ except Exception:
+ traceback.print_exc(file=sys.stderr, limit=0)
+ return False
+
+ def verify(self):
+ return self.fn is not None
+
+ def run(self, args, env):
+ result = None
+ try:
+ os.environ = env
+ self.global_context['param'] = args
+ exec('fun = %s(param)' % self.mainFn, self.global_context)
+ result = self.global_context['fun']
+ except Exception:
+ traceback.print_exc(file=sys.stderr)
+
+ if result and isinstance(result, dict):
+ return (200, result)
+ else:
+ return (502, {'error': 'The action did not return a dictionary.'})
+
+if __name__ == '__main__':
+ setRunner(PythonRunner())
+ main()
diff --git a/core/pythonAction/pythonrunner.py b/core/pythonAction/pythonrunner.py
index b6cc3d7..70df3fc 100644
--- a/core/pythonAction/pythonrunner.py
+++ b/core/pythonAction/pythonrunner.py
@@ -71,6 +71,7 @@
else:
sys.stderr.write('Invalid virtualenv. Zip file does not include /virtualenv/bin/' + os.path.basename(activate_this_file) + '\n')
return False
+ exec(self.fn, self.global_context)
return True
except Exception:
traceback.print_exc(file=sys.stderr, limit=0)
@@ -84,7 +85,6 @@
try:
os.environ = env
self.global_context['param'] = args
- exec(self.fn, self.global_context)
exec('fun = %s(param)' % self.mainFn, self.global_context)
result = self.global_context['fun']
except Exception:
diff --git a/tests/src/test/scala/runtime/actionContainers/PythonActionContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/PythonActionContainerTests.scala
index f36b8d9..132811b 100644
--- a/tests/src/test/scala/runtime/actionContainers/PythonActionContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/PythonActionContainerTests.scala
@@ -267,10 +267,7 @@
val (out, err) = withActionContainer() { c =>
val (initCode, initRes) = c.init(initPayload(code, main = "main"))
if (initErrorsAreLogged) {
- initCode should be(200)
- val args = JsObject("msg" -> JsString("any"))
- val (runCode, runRes) = c.run(runPayload(args))
- runCode should be(502)
+ initCode should be(502)
} else {
// it actually means it is actionloop
// it checks the error at init time
@@ -420,10 +417,7 @@
if (initErrorsAreLogged) {
val (initCode, res) = c.init(initPayload(code))
- initCode should be(200)
-
- val (runCode, runRes) = c.run(runPayload(JsObject()))
- runCode should be(502)
+ initCode should be(502)
} else {
// action loop detects those errors at init time
val (initCode, initRes) = c.init(initPayload(code))