Skip to content

Add support for Swift 5.4 #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ deploy:
branch: master
repo: apache/openwhisk-runtime-swift
- provider: script
script: "./tools/travis/publish.sh openwhisk 5.1 nightly && ./tools/travis/publish.sh openwhisk 5.3 nightly"
script: "./tools/travis/publish.sh openwhisk 5.1 nightly && ./tools/travis/publish.sh openwhisk 5.3 nightly && ./tools/travis/publish.sh openwhisk 5.4 nightly"
on:
branch: master
repo: apache/openwhisk-runtime-swift
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [Swift 4.2 CHANGELOG.md](core/swift42Action/CHANGELOG.md)
- [Swift 5.1 CHANGELOG.md](core/swift51Action/CHANGELOG.md)
- [Swift 5.3 CHANGELOG.md](core/swift53Action/CHANGELOG.md)
- [Swift 5.4 CHANGELOG.md](core/swift54Action/CHANGELOG.md)

## Quick Swift Action
### Simple swift action hello.swift
Expand Down
14 changes: 14 additions & 0 deletions ansible/files/runtimes.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@
"attachmentName": "codefile",
"attachmentType": "text/plain"
}
},
{
"kind": "swift:5.4",
"default": false,
"image": {
"prefix": "testing",
"name": "action-swift-v5.4",
"tag": "latest"
},
"deprecated": false,
"attached": {
"attachmentName": "codefile",
"attachmentType": "text/plain"
}
}
]
},
Expand Down
23 changes: 23 additions & 0 deletions core/swift54Action/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
#
# 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.
#
-->

# Apache OpenWhisk Swift 5.4 Runtime Container

## 1.16.0
- Initial Release
67 changes: 67 additions & 0 deletions core/swift54Action/Dockerfile
Original file line number Diff line number Diff line change
@@ -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.
#

# build go proxy from source
FROM golang:1.15 AS builder_source
ARG GO_PROXY_GITHUB_USER=apache
ARG GO_PROXY_GITHUB_BRANCH=master
RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \
https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\
cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \
mv proxy /bin/proxy

# or build it from a release
FROM golang:1.15 AS builder_release
ARG GO_PROXY_RELEASE_VERSION=1.15@1.17.0
RUN curl -sL \
https://github.com/apache/openwhisk-runtime-go/archive/{$GO_PROXY_RELEASE_VERSION}.tar.gz\
| tar xzf -\
&& cd openwhisk-runtime-go-*/main\
&& GO111MODULE=on go build -o /bin/proxy

FROM swift:5.4

# select the builder to use
ARG GO_PROXY_BUILD_FROM=release

RUN rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get -qq update \
&& apt-get install -y --no-install-recommends locales python3 vim libssl-dev libicu-dev \
&& 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_source /bin/proxy /bin/proxy_source
COPY --from=builder_release /bin/proxy /bin/proxy_release
RUN mv /bin/proxy_${GO_PROXY_BUILD_FROM} /bin/proxy
ADD swiftbuild.py /bin/compile
ADD swiftbuild.py.launcher.swift /bin/compile.launcher.swift
COPY _Whisk.swift /swiftAction/Sources/
COPY Package.swift /swiftAction/
COPY swiftbuildandlink.sh /swiftAction/
COPY main.swift /swiftAction/Sources/
RUN swift build -c release; \
touch /swiftAction/Sources/main.swift; \
rm /swiftAction/.build/release/Action

ENV OW_COMPILER=/bin/compile
ENTRYPOINT [ "/bin/proxy" ]
37 changes: 37 additions & 0 deletions core/swift54Action/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

/*
* 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 PackageDescription

let package = Package(
name: "Action",
products: [
.executable(
name: "Action",
targets: ["Action"]
)
],
targets: [
.target(
name: "Action",
path: "."
)
]
)
167 changes: 167 additions & 0 deletions core/swift54Action/_Whisk.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* 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 Foundation
import Dispatch
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

class Whisk {

static var baseUrl = ProcessInfo.processInfo.environment["__OW_API_HOST"]
static var apiKey = ProcessInfo.processInfo.environment["__OW_API_KEY"]
// This will allow user to modify the default JSONDecoder and JSONEncoder used by epilogue
static var jsonDecoder = JSONDecoder()
static var jsonEncoder = JSONEncoder()

class func invoke(actionNamed action : String, withParameters params : [String:Any], blocking: Bool = true) -> [String:Any] {
let parsedAction = parseQualifiedName(name: action)
let strBlocking = blocking ? "true" : "false"
let path = "/api/v1/namespaces/\(parsedAction.namespace)/actions/\(parsedAction.name)?blocking=\(strBlocking)"

return sendWhiskRequestSyncronish(uriPath: path, params: params, method: "POST")
}

class func trigger(eventNamed event : String, withParameters params : [String:Any]) -> [String:Any] {
let parsedEvent = parseQualifiedName(name: event)
let path = "/api/v1/namespaces/\(parsedEvent.namespace)/triggers/\(parsedEvent.name)?blocking=true"

return sendWhiskRequestSyncronish(uriPath: path, params: params, method: "POST")
}

class func createTrigger(triggerNamed trigger: String, withParameters params : [String:Any]) -> [String:Any] {
let parsedTrigger = parseQualifiedName(name: trigger)
let path = "/api/v1/namespaces/\(parsedTrigger.namespace)/triggers/\(parsedTrigger.name)"
return sendWhiskRequestSyncronish(uriPath: path, params: params, method: "PUT")
}

class func createRule(ruleNamed ruleName: String, withTrigger triggerName: String, andAction actionName: String) -> [String:Any] {
let parsedRule = parseQualifiedName(name: ruleName)
let path = "/api/v1/namespaces/\(parsedRule.namespace)/rules/\(parsedRule.name)"
let params = ["trigger":triggerName, "action":actionName]
return sendWhiskRequestSyncronish(uriPath: path, params: params, method: "PUT")
}

// handle the GCD dance to make the post async, but then obtain/return
// the result from this function sync
private class func sendWhiskRequestSyncronish(uriPath path: String, params : [String:Any], method: String) -> [String:Any] {
var response : [String:Any]!

let queue = DispatchQueue.global()
let invokeGroup = DispatchGroup()

invokeGroup.enter()
queue.async {
postUrlSession(uriPath: path, params: params, method: method, group: invokeGroup) { result in
response = result
}
}

// On one hand, FOREVER seems like an awfully long time...
// But on the other hand, I think we can rely on the system to kill this
// if it exceeds a reasonable execution time.
switch invokeGroup.wait(timeout: DispatchTime.distantFuture) {
case DispatchTimeoutResult.success:
break
case DispatchTimeoutResult.timedOut:
break
}

return response
}


/**
* Using new UrlSession
*/
private class func postUrlSession(uriPath: String, params : [String:Any], method: String,group: DispatchGroup, callback : @escaping([String:Any]) -> Void) {

guard let encodedPath = uriPath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else {
callback(["error": "Error encoding uri path to make openwhisk REST call."])
return
}

let urlStr = "\(baseUrl!)\(encodedPath)"
if let url = URL(string: urlStr) {
var request = URLRequest(url: url)
request.httpMethod = method

do {
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONSerialization.data(withJSONObject: params)

let loginData: Data = apiKey!.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let base64EncodedAuthKey = loginData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
request.addValue("Basic \(base64EncodedAuthKey)", forHTTPHeaderField: "Authorization")
let session = URLSession(configuration: URLSessionConfiguration.default)

let task = session.dataTask(with: request, completionHandler: {data, response, error -> Void in

// exit group after we are done
defer {
group.leave()
}

if let error = error {
callback(["error":error.localizedDescription])
} else {

if let data = data {
do {
//let outputStr = String(data: data, encoding: String.Encoding.utf8) as String!
//print(outputStr)
let respJson = try JSONSerialization.jsonObject(with: data)
if respJson is [String:Any] {
callback(respJson as! [String:Any])
} else {
callback(["error":" response from server is not a dictionary"])
}
} catch {
callback(["error":"Error creating json from response: \(error)"])
}
}
}
})

task.resume()
} catch {
callback(["error":"Got error creating params body: \(error)"])
}
}
}

// separate an OpenWhisk qualified name (e.g. "/whisk.system/samples/date")
// into namespace and name components
private class func parseQualifiedName(name qualifiedName : String) -> (namespace : String, name : String) {
let defaultNamespace = "_"
let delimiter = "/"

let segments :[String] = qualifiedName.components(separatedBy: delimiter)

if segments.count > 2 {
return (segments[1], Array(segments[2..<segments.count]).joined(separator: delimiter))
} else if segments.count == 2 {
// case "/action" or "package/action"
let name = qualifiedName.hasPrefix(delimiter) ? segments[1] : segments.joined(separator: delimiter)
return (defaultNamespace, name)
} else {
return (defaultNamespace, segments[0])
}
}

}
19 changes: 19 additions & 0 deletions core/swift54Action/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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.
*/

ext.dockerImageName = 'action-swift-v5.4'
apply from: '../../gradle/docker.gradle'
24 changes: 24 additions & 0 deletions core/swift54Action/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.
*/

func main(args: [String:Any]) -> [String:Any] {
if let name = args["name"] as? String {
return [ "greeting" : "Hello \(name)!" ]
} else {
return [ "greeting" : "Hello stranger!" ]
}
}
Loading