Support python actions with zip files.
Refactoring of init method into an init-from-source and init-from-zip.
Support a zip file containing more than one python file.
The zip file must contain a file called __main__.py that defines a "main" method.
Log an error when python zip does not include required file.
diff --git a/tests/src/actionContainers/PythonActionContainerTests.scala b/tests/src/actionContainers/PythonActionContainerTests.scala
index e62b7b3..ce25ffc 100644
--- a/tests/src/actionContainers/PythonActionContainerTests.scala
+++ b/tests/src/actionContainers/PythonActionContainerTests.scala
@@ -20,6 +20,8 @@
import org.scalatest.junit.JUnitRunner
import ActionContainer.withContainer
+import ResourceHelpers.ZipBuilder
+
import spray.json.DefaultJsonProtocol._
import spray.json._
import common.WskActorSystem
@@ -79,6 +81,59 @@
}
}
+ it should "support zip-encoded action using non-default entry points" in {
+ val srcs = Seq(
+ Seq("__main__.py") -> """
+ |from echo import echo
+ |def niam(args):
+ | return echo(args)
+ """.stripMargin,
+ Seq("echo.py") -> """
+ |def echo(args):
+ | return { "echo": args }
+ """.stripMargin)
+
+ val code = ZipBuilder.mkBase64Zip(srcs)
+
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(initPayload(code, main = "niam"))
+ initCode should be(200)
+
+ val args = JsObject("msg" -> JsString("it works"))
+ val (runCode, runRes) = c.run(runPayload(args))
+
+ runCode should be(200)
+ runRes.get.fields.get("echo") shouldBe Some(args)
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ o shouldBe empty
+ e shouldBe empty
+ })
+ }
+
+ it should "report error if zip-encoded action does not include required file" in {
+ val srcs = Seq(
+ Seq("echo.py") -> """
+ |def echo(args):
+ | return { "echo": args }
+ """.stripMargin)
+
+ val code = ZipBuilder.mkBase64Zip(srcs)
+
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(initPayload(code, main = "echo"))
+ initCode should be(502)
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ o shouldBe empty
+ e should include("Zip file does not include")
+ })
+ }
+
it should "handle unicode in source, input params, logs, and result" in {
val (out, err) = withActionContainer() { c =>
val code = """
@@ -140,9 +195,6 @@
val (initCode, res) = c.init(initPayload(code))
// init checks whether compilation was successful, so return 502
initCode should be(502)
-
- val (runCode, runRes) = c.run(runPayload(JsObject("basic" -> JsString("forever"))))
- runCode should be(502)
}
checkStreams(out, err, {
diff --git a/tests/src/actionContainers/SwiftActionContainerTests.scala b/tests/src/actionContainers/SwiftActionContainerTests.scala
index 73f6a20..85a4eb0 100644
--- a/tests/src/actionContainers/SwiftActionContainerTests.scala
+++ b/tests/src/actionContainers/SwiftActionContainerTests.scala
@@ -162,9 +162,6 @@
val (initCode, _) = c.init(initPayload(code))
initCode should not be (200)
-
- val (runCode, runRes) = c.run(runPayload(JsObject("basic" -> JsString("forever"))))
- runCode should be(502)
}
checkStreams(out, err, {
diff --git a/tests/src/system/basic/CLIPythonTests.scala b/tests/src/system/basic/CLIPythonTests.scala
index 9369e65..ff7ea82 100644
--- a/tests/src/system/basic/CLIPythonTests.scala
+++ b/tests/src/system/basic/CLIPythonTests.scala
@@ -64,6 +64,18 @@
}
}
+ it should "invoke an action from a zip file with a non-default entry point" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val name = "pythonZipWithNonDefaultEntryPoint"
+ assetHelper.withCleaner(wsk.action, name) {
+ (action, _) => action.create(name, Some(TestUtils.getTestActionFilename("python.zip")), main = Some("niam"), kind = Some("python"))
+ }
+
+ withActivation(wsk.activation, wsk.action.invoke(name, Map("name" -> "Prince".toJson))) {
+ _.response.result.get shouldBe JsObject("greeting" -> JsString("Hello Prince!"))
+ }
+ }
+
it should "invoke an action and confirm expected environment is defined" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
val name = "stdenv"