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 <[email protected]> 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 = [
