You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2019/01/08 02:33:05 UTC
[incubator-openwhisk-runtime-swift] 01/02: switf4.2.1 with
actionloop base implementation
This is an automated email from the ASF dual-hosted git repository.
csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-runtime-swift.git
commit 3fb47475f95f663d905229f493c42eddd0f4d595
Author: Michele Sciabarra <mi...@sciabarra.com>
AuthorDate: Sat Nov 17 13:02:54 2018 +0100
switf4.2.1 with actionloop base implementation
whitespaces and headers...
---
.gitignore | 4 +
core/swift421ActionLoop/Dockerfile | 39 ++++++
.../swift421ActionLoop/build.gradle | 23 +---
core/swift421ActionLoop/swiftbuild.py | 133 +++++++++++++++++++++
.../swiftbuild.py.launcher.swift | 67 +++++++++++
examples/swift-main-single/Makefile | 35 ++++++
.../swift-main-single/main.swift | 28 ++---
settings.gradle | 2 +
8 files changed, 289 insertions(+), 42 deletions(-)
diff --git a/.gitignore b/.gitignore
index 039da65..6dc577b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,7 @@ ansible/roles/nginx/files/*cert.pem
!tests/dat/build/swift4.1/SwiftyRequestCodable.zip
!tests/dat/build/swift4.1/HelloSwift4Codable.zip
+# Makefile artifacts
+test.json
+*.done
+examples/swift-main-single/main.zip
diff --git a/core/swift421ActionLoop/Dockerfile b/core/swift421ActionLoop/Dockerfile
new file mode 100644
index 0000000..506da76
--- /dev/null
+++ b/core/swift421ActionLoop/Dockerfile
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+FROM openwhisk/actionloop as builder
+
+FROM swift:4.2.1
+
+RUN rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get update \
+ && apt-get install -y --no-install-recommends locales python3 \
+ && rm -rf /var/lib/apt/lists/* \
+ && locale-gen en_US.UTF-8
+
+ENV LANG="en_US.UTF-8" \
+ LANGUAGE="en_US:en" \
+ LC_ALL="en_US.UTF-8"
+
+RUN mkdir -p /swiftAction
+WORKDIR /swiftAction
+
+
+COPY --from=builder /bin/proxy /bin/proxy
+ADD swiftbuild.py /bin/compile
+ADD swiftbuild.py.launcher.swift /bin/compile.launcher.swift
+
+ENV OW_COMPILER=/bin/compile
+ENTRYPOINT [ "/bin/proxy" ]
diff --git a/settings.gradle b/core/swift421ActionLoop/build.gradle
old mode 100644
new mode 100755
similarity index 64%
copy from settings.gradle
copy to core/swift421ActionLoop/build.gradle
index 0009fa4..d9bb28f
--- a/settings.gradle
+++ b/core/swift421ActionLoop/build.gradle
@@ -15,24 +15,5 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation', '-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+ext.dockerImageName = 'actionloop-swift-v4.2.1'
+apply from: '../../gradle/docker.gradle'
diff --git a/core/swift421ActionLoop/swiftbuild.py b/core/swift421ActionLoop/swiftbuild.py
new file mode 100755
index 0000000..49ec29d
--- /dev/null
+++ b/core/swift421ActionLoop/swiftbuild.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python3
+"""Swift Action Compiler
+#
+# 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.
+#
+"""
+
+from __future__ import print_function
+import os
+import re
+import sys
+import codecs
+import subprocess
+from io import StringIO
+
+package_swift = """// swift-tools-version:4.2
+import PackageDescription
+
+let package = Package(
+ name: "exec",
+ dependencies: [],
+ targets: [
+ .target(
+ name: "exec",
+ dependencies: [])
+ ]
+)
+"""
+output = StringIO()
+
+def eprint(*args, **kwargs):
+ print(*args, file=output, **kwargs)
+
+def sources(launcher, source_dir, main):
+ # create Packages.swift
+ packagefile = "%s/Package.swift" % source_dir
+ if not os.path.isfile(packagefile):
+ with codecs.open(packagefile, 'w', 'utf-8') as s:
+ s.write(package_swift)
+
+ # create Sources/Action dir
+ actiondir = "%s/Sources/exec" % source_dir
+ if not os.path.isdir(actiondir):
+ os.makedirs(actiondir, mode=0o755)
+
+ # copy the exec to exec.go
+ # also check if it has a main in it
+ src = "%s/exec" % source_dir
+ dst = "%s/exec.swift" % actiondir
+ if os.path.isfile(src):
+ with codecs.open(src, 'r', 'utf-8') as s:
+ with codecs.open(dst, 'w', 'utf-8') as d:
+ body = s.read()
+ d.write(body)
+
+ # copy the launcher fixing the main
+ dst = "%s/main.swift" % actiondir
+ with codecs.open(dst, 'w', 'utf-8') as d:
+ with codecs.open(launcher, 'r', 'utf-8') as e:
+ code = e.read()
+ code += "_run_main(mainFunction: %s)\n" % main
+ d.write(code)
+
+def swift_build(dir, extra_args=[]):
+ base_args = ["swift", "build", "--package-path", dir, "-c", "release"]
+ # compile...
+ env = {
+ "PATH": os.environ["PATH"]
+ }
+ p = subprocess.Popen(base_args+extra_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=dir,
+ env=env)
+ (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
+ if isinstance(o, bytes) and not isinstance(o, str):
+ o = o.decode('utf-8')
+ if isinstance(e, bytes) and not isinstance(e, str):
+ e = e.decode('utf-8')
+ return p.returncode, o, e
+
+def build(source_dir, target_file):
+ r, o, e = swift_build(source_dir)
+ if e: eprint(e)
+ if o: eprint(o)
+ if r != 0:
+ print(output.getvalue())
+ return
+
+ r, o, e = swift_build(source_dir, ["--show-bin-path"])
+ if e: eprint(e)
+ if r != 0:
+ print(output.getvalue())
+ return
+
+ bin_file = "%s/exec" % o.strip()
+ os.rename(bin_file, target_file)
+ if not os.path.isfile(target_file):
+ eprint("failed %s -> %s" % (bin_file, target_file))
+ print(output.getvalue())
+ return
+
+
+def main(argv):
+ if len(argv) < 4:
+ print("usage: <main-function> <source-dir> <target-dir>")
+ sys.exit(1)
+
+ main = argv[1]
+ source_dir = os.path.abspath(argv[2])
+ target = os.path.abspath("%s/exec" % argv[3])
+ launch = os.path.abspath(argv[0]+".launcher.swift")
+ sources(launch, source_dir, main)
+ build(source_dir, target)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/core/swift421ActionLoop/swiftbuild.py.launcher.swift b/core/swift421ActionLoop/swiftbuild.py.launcher.swift
new file mode 100644
index 0000000..de649ab
--- /dev/null
+++ b/core/swift421ActionLoop/swiftbuild.py.launcher.swift
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+// Imports
+import Foundation
+#if os(Linux)
+ import Glibc
+#else
+ import Darwin
+#endif
+
+func _whisk_print_error(message: String, error: Error?){
+ var errStr = "{\"error\":\"\(message)\"}\n"
+ if let error = error {
+ errStr = "{\"error\":\"\(message) \(error.localizedDescription)\"\n}"
+ }
+ let buf : [UInt8] = Array(errStr.utf8)
+ write(3, buf, buf.count)
+}
+
+// snippet of code "injected" (wrapper code for invoking traditional main)
+func _run_main(mainFunction: ([String: Any]) -> [String: Any]) -> Void {
+ while let inputStr: String = readLine() {
+ do {
+ let json = inputStr.data(using: .utf8, allowLossyConversion: true)!
+ let parsed = try JSONSerialization.jsonObject(with: json, options: []) as! [String: Any]
+ // TODO put the values in the env
+ let value = parsed["value"] as! [String: Any]
+ let result = mainFunction(value)
+ if JSONSerialization.isValidJSONObject(result) {
+ do {
+ let jsonData = try JSONSerialization.data(withJSONObject: result, options: [])
+ var json = [UInt8](jsonData)
+ json.append(10)
+ write(3, json, json.count)
+ fflush(stdout)
+ fflush(stderr)
+ } catch {
+ _whisk_print_error(message: "Failed to encode Dictionary type to JSON string:", error: error)
+ }
+ } else {
+ _whisk_print_error(message: "Error serializing JSON, data does not appear to be valid JSON", error: nil)
+ }
+ } catch {
+ _whisk_print_error(message: "Failed to execute action handler with error:", error: error)
+ return
+ }
+ }
+}
+
+// snippets of code "injected", dependending on the type of function the developer
+// wants to use traditional vs codable
+
diff --git a/examples/swift-main-single/Makefile b/examples/swift-main-single/Makefile
new file mode 100644
index 0000000..0545f1b
--- /dev/null
+++ b/examples/swift-main-single/Makefile
@@ -0,0 +1,35 @@
+OW_USER?=openwhisk
+OW_RUNTIME?=$(OW_USER)/actionloop-swift-v4.2.1
+OW_COMPILER?=$(OW_USER)/actionloop-swift-v4.2.1
+WSK?=wsk
+MAIN=main
+PACKAGE=test
+SRC=$(MAIN).swift
+NAME=swift-$(MAIN)-single
+ZIP=$(MAIN).zip
+
+deploy: package.done $(ZIP)
+ $(WSK) action update $(PACKAGE)/$(NAME) $(ZIP) --main $(MAIN) --docker $(OW_RUNTIME)
+
+devel: package.done $(SRC)
+ $(WSK) action update $(PACKAGE)/$(NAME) $(SRC) --main $(MAIN) --docker $(OW_COMPILER)
+
+$(ZIP): $(SRC)
+ docker run -i $(OW_COMPILER) -compile $(MAIN) <$(SRC) >$(ZIP)
+
+clean:
+ wsk action delete $(PACKAGE)/$(NAME)
+ rm $(ZIP) package.done
+
+test: test.json
+ $(WSK) action invoke test/$(NAME) -r
+ $(WSK) action invoke test/$(NAME) -P test.json -r
+
+test.json:
+ echo '{ "name": "Mike" }' >test.json
+
+package.done:
+ $(WSK) package update $(PACKAGE)
+ touch package.done
+
+.PHONY: deploy devel test clean
diff --git a/settings.gradle b/examples/swift-main-single/main.swift
similarity index 64%
copy from settings.gradle
copy to examples/swift-main-single/main.swift
index 0009fa4..7d8521e 100644
--- a/settings.gradle
+++ b/examples/swift-main-single/main.swift
@@ -15,24 +15,10 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation', '-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+func main(args: [String:Any]) -> [String:Any] {
+ if let name = args["name"] as? String {
+ return [ "greeting" : "Hello \(name)!" ]
+ } else {
+ return [ "greeting" : "Hello swif4!" ]
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 0009fa4..4627e15 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -21,6 +21,8 @@ include 'core:swift3.1.1Action'
include 'core:swift41Action'
+include 'core:swift421ActionLoop'
+
rootProject.name = 'runtime-swift'
gradle.ext.openwhisk = [