Server(less) Swift
with Kitura and OpenWhisk
Chris Bailey
@Chris__Bailey
FrenchKit 2017
September 22nd
2
(less) SwiftServer
3
SwiftServer
4
FullStack
0
17.5
35
52.5
70
FullStack
Backend
Frontend
11.9
24.4
63.7
5
FullStack
0
17.5
35
52.5
70
FullStack
Backend
Frontend
11.9
24.4
63.7
0
40
80
120
160
141.5
16.2
4.34
Fast
6
FullStack
0
17.5
35
52.5
70
FullStack
Backend
Frontend
11.9
24.4
63.7
0
40
80
120
160
141.5
16.2
4.34
Fast
0
15
30
45
60
50.2
31.3
29.9
11.7
Efficient
7
iOS APP
Hosted Services
GATEWAY
PUBLIC NETWORK CLOUD NETWORK
SWAGGER
DATA
PUSH ANALYTICS
DEVOPS AVAILABILITY MONITORINGSCALING
SOCIAL
COGNATIVE
AUTH
WEB APP
8
import Kitura
import SwiftyJSON
9
import Kitura
import SwiftyJSON
router.all("/*", middleware: BodyParser())
router.post(path, handler: handleCreate)
10
import Kitura
import SwiftyJSON
router.all("/*", middleware: BodyParser())
router.post(path, handler: handleCreate)
func handleCreate(request: RouterRequest, response: RouterResponse,
next: @escaping () -> Void) {
}
11
import Kitura
import SwiftyJSON
router.all("/*", middleware: BodyParser())
router.post(path, handler: handleCreate)
func handleCreate(request: RouterRequest, response: RouterResponse,
next: @escaping () -> Void) {
guard case .json(let json)? = request.body else {
response.status(.badRequest)
response.send(json: JSON([ "error": "Request not JSON" ]))
return next()
}
}
12
import Kitura
import SwiftyJSON
router.all("/*", middleware: BodyParser())
router.post(path, handler: handleCreate)
func handleCreate(request: RouterRequest, response: RouterResponse,
next: @escaping () -> Void) {
guard case .json(let json)? = request.body else {
response.status(.badRequest)
response.send(json: JSON([ "error": "Request not JSON" ]))
return next()
}
let name = json["name"].string
let rating = json[“rating"].number
// etc
// etc
}
13
import Kitura
import SwiftyJSON
router.all("/*", middleware: BodyParser())
router.post(path, handler: handleCreate)
func handleCreate(request: RouterRequest, response: RouterResponse,
next: @escaping () -> Void) {
guard case .json(let json)? = request.body else {
response.status(.badRequest)
response.send(json: JSON([ "error": "Request not JSON" ]))
return next()
}
let name = json["name"].string
let rating = json[“rating"].number
// etc
// etc
next()
}
14
15
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
16
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
17
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
CaaS
18
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
CaaS
PaaS
19
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
CaaS
PaaS
?
20
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
IaaS
CaaS
PaaS
? Serverless
Serverless
21
Functions-as-a-Service
22
PaaS FaaS
OpenWhisk
23
PaaS
Write application centric business
logic.
FaaS
Write event-driven business logic.

OpenWhisk
24
PaaS
Write application centric business
logic.
Treat compute resources as utilities.
FaaS
Write event-driven business logic.







Treat compute resources as utilities.
OpenWhisk
25
PaaS
Write application centric business
logic.
Treat compute resources as utilities.
Provides scaling, resilience and
availability
FaaS
Write event-driven business logic.







Treat compute resources as utilities.
Provides scaling, resilience and

availability
OpenWhisk
26
“If your PaaS can efficiently start instances in 20ms

that run for half a second, then call it serverless.”
- Adrian Cockcroft
27
28
29
func main(args: [String:Any]) -> [String:Any] {
// Action code
// goes here
return [ “result" : "value" ]
}
30
func main(args: [String:Any]) -> [String:Any] {
// Action code
// goes here
return [ “result" : "value" ]
}
Entry Point
31
func main(args: [String:Any]) -> [String:Any] {
// Action code
// goes here
return [ “result" : "value" ]
}
Entry Point Event Parameters
32
func main(args: [String:Any]) -> [String:Any] {
// Action code
// goes here
return [ “result" : "value" ]
}
Entry Point Event Parameters
Result
33
func main(args: [String:Any]) -> [String:Any] {
}
34
func main(args: [String:Any]) -> [String:Any] {
if let name = args["name"] as? String {
}
}
35
func main(args: [String:Any]) -> [String:Any] {
if let name = args["name"] as? String {
return [ "greeting" : "Hello (name)!" ]
}
}
36
func main(args: [String:Any]) -> [String:Any] {
if let name = args["name"] as? String {
return [ "greeting" : "Hello (name)!" ]
} else {
return [ "greeting" : "Hello stranger!" ]
}
}
37
$ git clone https://github.com/openwhisk/openwhisk.git
Get OpenWhisk
38
$ git clone https://github.com/openwhisk/openwhisk.git
$ cd openwhisk/tools/vagrant
$ vagrant up
Get OpenWhisk
39
$ git clone https://github.com/openwhisk/openwhisk.git
$ cd openwhisk/tools/vagrant
$ vagrant up
Get OpenWhisk
Start OpenWhisk
(in a Linux VM)
40
$ wsk action create hello main.swift

41
$ wsk action create hello main.swift

42
Create
Action
$ wsk action create hello main.swift

43
Create
Action Called
$ wsk action create hello main.swift

44
Create
Action Called From
$ wsk action create hello main.swift

ok: created action hello
45
Create
Action Called From
$ wsk action create hello main.swift

ok: created action hello
$ wsk action list
46
Create
Action Called From
$ wsk action create hello main.swift

ok: created action hello
$ wsk action list
actions
hello private
47
Create
Action Called From
$ wsk action create hello main.swift

ok: created action hello
$ wsk action list
actions
hello private
48
Create
Action
Our Action
Called From
$ wsk action invoke --result hello --param name World


49
$ wsk action invoke --result hello --param name World


50
Invoke
Action
$ wsk action invoke --result hello --param name World


51
Invoke
Action Called
$ wsk action invoke --result hello --param name World


52
Invoke
Action Called
With
Parameters
$ wsk action invoke --result hello --param name World
{
“greeting" : “Hello World!”
}

53
Invoke
Action Called
With
Parameters
54
T
Triggers
• Database update
• IoT sensor activation
• GitHub hook
• Slack notification
• REST request
T
55
T A
Triggers
• Database update
• IoT sensor activation
• GitHub hook
• Slack notification
• REST request
Actions
• Your code
• Single task
• Any language
• Docker binary
• Returns JSON
AT
56
T A R
Triggers
• Database update
• IoT sensor activation
• GitHub hook
• Slack notification
• REST request
Actions
• Your code
• Single task
• Any language
• Docker binary
• Returns JSON
Rules
• Link Triggers to

Actions
• Create sequences
• Many to many maps

become possible
ATR :=
57
T A R
Triggers
• Database update
• IoT sensor activation
• GitHub hook
• Slack notification
• REST request
Actions
• Your code
• Single task
• Any language
• Docker binary
• Returns JSON
Rules
• Link Triggers to

Actions
• Create sequences
• Many to many maps

become possible
ATR A
A1
A2
A3
:= + +:=
58
T A R P
Triggers
• Database update
• IoT sensor activation
• GitHub hook
• Slack notification
• REST request
Actions
• Your code
• Single task
• Any language
• Docker binary
• Returns JSON
Rules
• Link Triggers to

Actions
• Create sequences
• Many to many maps

become possible
Packages
• Collection of triggers
and actions
ATR A
A1
A2
A3
AB
A2
A1
A4TR
:=
:=
+
+
+
+
:=
:=
$ wsk api create /hello get hello —response-type json
59
$ wsk api create /hello get hello —response-type json
60
Create
API
$ wsk api create /hello get hello —response-type json
61
Create
API
REST
Route Method
$ wsk api create /hello get hello —response-type json
62
Create
API
REST
Route Method
From
Action
$ wsk api create /hello get hello —response-type json
ok: created API /hello GET for action /_/hello
https://${APIHOST}:9001/api/21ef035/hello
63
Create
API
REST
Route Method
From
Action
$ wsk api create /hello get hello —response-type json
ok: created API /hello GET for action /_/hello
https://${APIHOST}:9001/api/21ef035/hello
$ curl https://${APIHOST}:9001/api/21ef035/hello?
name=World
64
Create
API
REST
Route Method
From
Action
65
66
• Mobile client SDK for iOS and watchOS.
• Fire remote triggers and invoke remote
actions.
• Swift 3, iOS9+ and watchOS 3.
• Install by using CocoaPods, Carthage,
Swift Package Manager, or from the
source directory.
https://github.com/apache/incubator-openwhisk-client-swift
var params = [String: String]()
params["payload"] = "Hello"
67
var params = [String: String]()
params["payload"] = "Hello"
do {
try whisk.invokeAction(name: "hello", parameters: params,

hasResult: true, callback:
{(reply, error) -> Void in
})
} catch {
print("Error (error)")
}
68
var params = [String: String]()
params["payload"] = "Hello"
do {
try whisk.invokeAction(name: "hello", parameters: params,

hasResult: true, callback:
{(reply, error) -> Void in
if let error = error {
print("Error invoking action (error.localizedDescription)")
} else {
var result = reply["result"]
print("Got result (result)")
}
})
} catch {
print("Error (error)")
}
69
70
Weather Gods
Weather Gods
• Premium app from Meyume Ltd.
• Offers a rich interactive experience
unlike other weather apps.
• Sources high quality weather data from
multiple providers including The
Weather Company.
• Provides weather notifications:
• type (rain, snow etc.)
• schedule (evening, morning, or live)
• options (e.g. only notify about heavy
rain).
71
72
3-minute
alarm
Group
scanner
Weather
collector
Wind
scanner
Rain
scanner
Fog
scanner
Alarm
trigger
Alarm
trigger
Alarm
trigger
Send
push
Send
push
Send
push
Push
notification
service
73
BluePic
74
BluePic
• Sample app from IBM
• iOS and Web front ends
• Provides photo sharing
• Adds image recognition and weather
data to the photo
• Provides notifications to users
• Social sharing
• Updates to data
https://github.com/IBM/BluePic
75
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
76
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
77
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
78
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
79
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
80
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
81
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
82
PUBLIC NETWORK CLOUD NETWORK
iOS APP
WEB APP
83
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
84
Decreasing concern (and control)
over stack implementation
Increasingfocusonbusinesslogic
Server
Serverless

FrenchKit 2017: Server(less) Swift