1 | # Serverless OpenWhisk Plugin
|
2 | [![Build Status](https://travis-ci.org/serverless/serverless-openwhisk.svg?branch=master)](https://travis-ci.org/serverless/serverless-openwhisk)
|
3 | [![codecov](https://codecov.io/gh/serverless/serverless-openwhisk/branch/master/graph/badge.svg)](https://codecov.io/gh/serverless/serverless-openwhisk)
|
4 |
|
5 | This plugin enables support for the [OpenWhisk platform](http://openwhisk.org/) within the Serverless Framework.
|
6 |
|
7 | ## Getting Started
|
8 |
|
9 | ### Register account with OpenWhisk
|
10 |
|
11 | Before you can deploy your service to OpenWhisk, you need to have an account registered with the platform.
|
12 |
|
13 | - *Want to run the platform locally?* Please read the project's [*Quick Start*](https://github.com/openwhisk/openwhisk#quick-start) guide for deploying it locally.
|
14 | - *Want to use a hosted provider?* Please sign up for an account with [IBM Bluemix](https://console.ng.bluemix.net/) and then follow the instructions for getting access to [OpenWhisk on Bluemix](https://console.ng.bluemix.net/openwhisk/).
|
15 |
|
16 | ### Set up account credentials
|
17 |
|
18 | Account credentials for OpenWhisk can be provided through a configuration file or environment variables. This plugin requires the API endpoint, namespace and authentication credentials.
|
19 |
|
20 | **Do you want to use a configuration file for storing these values?** Please [follow the instructions](https://console.ng.bluemix.net/openwhisk/cli) for setting up the OpenWhisk command-line utility. This tool stores account credentials in the `.wskprops` file in the user's home directory. The plugin automatically extracts credentials from this file at runtime. No further configuration is needed.
|
21 |
|
22 | **Do you want to use environment variables for credentials?** Use the following environment variables to be pass in account credentials. These values override anything extracted from the configuration file.
|
23 |
|
24 | - *OW_APIHOST* - Platform endpoint, e.g. `openwhisk.ng.bluemix.net`
|
25 | - *OW_AUTH* - Authentication key, e.g. `xxxxxx:yyyyy`
|
26 | - *OW_APIGW_ACCESS_TOKEN* - API gateway access token (optional)
|
27 |
|
28 | ### Install Framework & Dependencies
|
29 |
|
30 | *Due to an [outstanding issue](https://github.com/serverless/serverless/issues/2895) with provider plugins, the [OpenWhisk provider](https://github.com/serverless/serverless-openwhisk) must be installed as a global module.*
|
31 |
|
32 | ```shell
|
33 | $ npm install --global serverless serverless-openwhisk
|
34 | ```
|
35 |
|
36 | **_This framework plugin requires Node.js runtime version 6.0 or above._**
|
37 |
|
38 | ### Create Service From Template
|
39 |
|
40 | Using the `create` command, you can create an example service from the [following template](https://github.com/serverless/serverless/tree/master/lib/plugins/create/templates/openwhisk-nodejs).
|
41 |
|
42 | ```shell
|
43 | serverless create --template openwhisk-nodejs --path my_service
|
44 | cd my_service
|
45 | npm install
|
46 | ```
|
47 |
|
48 | More service examples are available in the [`serverless-examples`](https://github.com/serverless/examples) repository.
|
49 |
|
50 | **Using a self-hosted version of the platform?**
|
51 |
|
52 | Ensure you set the `ignore_certs` option in the serverless.yaml prior to deployment.
|
53 |
|
54 | ```
|
55 | provider:
|
56 | name: openwhisk
|
57 | ignore_certs: true
|
58 | ```
|
59 |
|
60 | ### Deploy Service
|
61 |
|
62 | The sample service from the template can be deployed without modification.
|
63 |
|
64 | ```shell
|
65 | serverless deploy
|
66 | ```
|
67 |
|
68 | If the deployment succeeds, the following messages will be printed to the console.
|
69 |
|
70 | ```sh
|
71 | $ serverless deploy
|
72 | Serverless: Packaging service...
|
73 | Serverless: Compiling Functions...
|
74 | Serverless: Compiling API Gateway definitions...
|
75 | Serverless: Compiling Rules...
|
76 | Serverless: Compiling Triggers & Feeds...
|
77 | Serverless: Deploying Functions...
|
78 | Serverless: Deployment successful!
|
79 |
|
80 | Service Information
|
81 | platform: openwhisk.ng.bluemix.net
|
82 | namespace: _
|
83 | service: my_service
|
84 |
|
85 | actions:
|
86 | my_service-dev-hello
|
87 |
|
88 | triggers:
|
89 | **no triggers deployed***
|
90 |
|
91 | rules:
|
92 | **no rules deployed**
|
93 |
|
94 | endpoints:
|
95 | **no routes deployed**
|
96 |
|
97 | web-actions:
|
98 | **no web actions deployed**
|
99 | ```
|
100 |
|
101 | ### Test Service
|
102 |
|
103 | Use the `invoke` command to test your newly deployed service.
|
104 |
|
105 | ```shell
|
106 | $ serverless invoke --function hello
|
107 | {
|
108 | "payload": "Hello, World!"
|
109 | }
|
110 | $ serverless invoke --function hello --data '{"name": "OpenWhisk"}'
|
111 | {
|
112 | "payload": "Hello, OpenWhisk!"
|
113 | }
|
114 | ```
|
115 |
|
116 | ## Writing Functions - Node.js
|
117 |
|
118 | Here's an `index.js` file containing an example handler function.
|
119 |
|
120 | ```javascript
|
121 | function main(params) {
|
122 | const name = params.name || 'World';
|
123 | return {payload: 'Hello, ' + name + '!'};
|
124 | };
|
125 |
|
126 | exports.main = main;
|
127 | ```
|
128 |
|
129 | Modules [should return the function handler](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#packaging-an-action-as-a-nodejs-module) as a custom property on the global `exports` object.
|
130 |
|
131 | In the `serverless.yaml` file, the `handler` property is used to denote the source file and module property containing the serverless function.
|
132 |
|
133 | ```yaml
|
134 | functions:
|
135 | my_function:
|
136 | handler: index.main
|
137 | ```
|
138 |
|
139 | ### Request Properties
|
140 |
|
141 | OpenWhisk executes the handler function for each request. This function is called with a single argument, an object [containing the request properties](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#passing-parameters-to-an-action).
|
142 |
|
143 | ```javascript
|
144 | function main(params) {
|
145 | const parameter = params.parameter_name;
|
146 | ...
|
147 | };
|
148 | ```
|
149 |
|
150 | ### Function Return Values
|
151 |
|
152 | The handler must return an object from the function call. Returning `undefined` or `null` will result in an error. If the handler is carrying out an [asynchronous task](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#creating-asynchronous-actions), it can return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
|
153 |
|
154 | ```javascript
|
155 | // synchronous return
|
156 | function main () {
|
157 | return { payload: "..." }
|
158 | }
|
159 |
|
160 | // asychronous return
|
161 | function main(args) {
|
162 | return new Promise(function(resolve, reject) {
|
163 | setTimeout(function() {
|
164 | resolve({ done: true });
|
165 | }, 2000);
|
166 | })
|
167 | }
|
168 | ```
|
169 |
|
170 | If you want to return an error message, return an object with an `error` property with the message. Promise values that are rejected will be interpreted as runtime errors.
|
171 |
|
172 | ```javascript
|
173 | // synchronous return
|
174 | function main () {
|
175 | return { error: "..." }
|
176 | }
|
177 |
|
178 | // asychronous return
|
179 | function main(args) {
|
180 | return new Promise(function(resolve, reject) {
|
181 | setTimeout(function() {
|
182 | reject("error message");
|
183 | }, 2000);
|
184 | })
|
185 | }
|
186 | ```
|
187 |
|
188 | ### Using NPM Modules
|
189 |
|
190 | NPM modules must be [installed locally](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#packaging-an-action-as-a-nodejs-module) in the `node_modules` directory before deployment. This directory will be packaged up in the deployment artefact. Any dependencies included in `node_modules` will be available through `require()` in the runtime environment.
|
191 |
|
192 | OpenWhisk provides a number of popular NPM modules in the runtime environment. Using these modules doesn't require them to be included in the deployment package. See [this list](https://github.com/openwhisk/openwhisk/blob/master/docs/reference.md#javascript-runtime-environments) for full details of which modules are available.
|
193 |
|
194 | ```javascript
|
195 | const leftPad = require("left-pad")
|
196 |
|
197 | function pad_lines(args) {
|
198 | const lines = args.lines || [];
|
199 | return { padded: lines.map(l => leftPad(l, 30, ".")) }
|
200 | };
|
201 |
|
202 | exports.handler = pad_lines;
|
203 | ```
|
204 |
|
205 | ## Writing Functions - PHP
|
206 |
|
207 | Here's an `index.php` file containing an example handler function.
|
208 |
|
209 | ```php
|
210 | <?php
|
211 | function main(array $args) : array
|
212 | {
|
213 | $name = $args["name"] ?? "stranger";
|
214 | $greeting = "Hello $name!";
|
215 | echo $greeting;
|
216 | return ["greeting" => $greeting];
|
217 | }
|
218 | ```
|
219 |
|
220 | In the `serverless.yaml` file, the `handler` property is used to denote the source file and function name of the serverless function.
|
221 |
|
222 | ```yaml
|
223 | functions:
|
224 | my_function:
|
225 | handler: index.main
|
226 | runtime: php
|
227 | ```
|
228 |
|
229 | ### Request Properties
|
230 |
|
231 | OpenWhisk executes the handler function for each request. This function is called with a single argument, an associative array [containing the request properties](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#passing-parameters-to-an-action).
|
232 |
|
233 | ```php
|
234 | function main(array $args) : array
|
235 | {
|
236 | $name = $args["name"] ?? "stranger";
|
237 | ...
|
238 | }
|
239 | ```
|
240 |
|
241 | ### Function Return Values
|
242 |
|
243 | The handler must return an associative array from the function call.
|
244 |
|
245 | ```swift
|
246 | func main(args: [String:Any]) -> [String:Any] {
|
247 | ...
|
248 | return ["foo" => $bar];
|
249 | }
|
250 | ```
|
251 |
|
252 | If you want to return an error message, return an object with an `error` property with the message.
|
253 |
|
254 | ## Writing Functions - Python
|
255 |
|
256 | Here's an `index.py` file containing an example handler function.
|
257 |
|
258 | ```python
|
259 | def endpoint(params):
|
260 | name = params.get("name", "stranger")
|
261 | greeting = "Hello " + name + "!"
|
262 | print(greeting)
|
263 | return {"greeting": greeting}
|
264 | ```
|
265 |
|
266 | In the `serverless.yaml` file, the `handler` property is used to denote the source file and module property containing the serverless function.
|
267 |
|
268 | ```yaml
|
269 | functions:
|
270 | my_function:
|
271 | handler: index.endpoint
|
272 | runtime: python
|
273 | ```
|
274 |
|
275 | ### Request Properties
|
276 |
|
277 | OpenWhisk executes the handler function for each request. This function is called with a single argument, a dictionary [containing the request properties](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#passing-parameters-to-an-action).
|
278 |
|
279 | ```python
|
280 | def endpoint(params):
|
281 | name = params.get("name", "stranger")
|
282 | ...
|
283 | ```
|
284 |
|
285 | ### Function Return Values
|
286 |
|
287 | The handler must return a dictionary from the function call.
|
288 |
|
289 | ```python
|
290 | def endpoint(params):
|
291 | ...
|
292 | return {"foo": "bar"}
|
293 | ```
|
294 |
|
295 | If you want to return an error message, return an object with an `error` property with the message.
|
296 |
|
297 | ## Writing Functions - Swift
|
298 |
|
299 | Here's an `index.swift` file containing an example handler function.
|
300 |
|
301 | ```swift
|
302 | func main(args: [String:Any]) -> [String:Any] {
|
303 | if let name = args["name"] as? String {
|
304 | return [ "greeting" : "Hello \(name)!" ]
|
305 | } else {
|
306 | return [ "greeting" : "Hello stranger!" ]
|
307 | }
|
308 | }
|
309 | ```
|
310 |
|
311 | In the `serverless.yaml` file, the `handler` property is used to denote the source file and module property containing the serverless function.
|
312 |
|
313 | ```yaml
|
314 | functions:
|
315 | my_function:
|
316 | handler: index.main
|
317 | runtime: swift
|
318 | ```
|
319 |
|
320 | ### Request Properties
|
321 |
|
322 | OpenWhisk executes the handler function for each request. This function is called with a single argument, a dictionary [containing the request properties](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#passing-parameters-to-an-action).
|
323 |
|
324 | ```swift
|
325 | func main(args: [String:Any]) -> [String:Any] {
|
326 | let prop = args["prop"] as? String
|
327 | }
|
328 | ```
|
329 |
|
330 | ### Function Return Values
|
331 |
|
332 | The handler must return a dictionary from the function call.
|
333 |
|
334 | ```swift
|
335 | func main(args: [String:Any]) -> [String:Any] {
|
336 | ...
|
337 | return ["foo": "bar"]
|
338 | }
|
339 | ```
|
340 |
|
341 | If you want to return an error message, return an object with an `error` property with the message.
|
342 |
|
343 | ## Writing Functions - Pre-Compiled Swift Binaries
|
344 |
|
345 | OpenWhisk supports creating Swift actions from a pre-compiled binary. This reduces startup time for Swift actions by removing the need for a dynamic compilation step.
|
346 |
|
347 | In the `serverless.yaml` file, the `handler` property can refer to the compiled binary file produced by the build.
|
348 |
|
349 | ```yaml
|
350 | functions:
|
351 | hello:
|
352 | handler: .build/release/Hello
|
353 | ```
|
354 |
|
355 | This configuration will generate the deployment package for that function containing only this binary file. It will not include other local files, e.g. Swift source files.
|
356 |
|
357 | Pre-compiled Swift actions must be compatible with the platform runtime and architecture. There is an [open-source Swift package](https://packagecatalog.com/package/jthomas/OpenWhiskAction) (`OpenWhiskAction`) that handles wrapping functions within a shim to support runtime execution.
|
358 |
|
359 | ```
|
360 | import OpenWhiskAction
|
361 |
|
362 | func hello(args: [String:Any]) -> [String:Any] {
|
363 | if let name = args["name"] as? String {
|
364 | return [ "greeting" : "Hello \(name)!" ]
|
365 | } else {
|
366 | return [ "greeting" : "Hello stranger!" ]
|
367 | }
|
368 | }
|
369 |
|
370 | OpenWhiskAction(main: hello)
|
371 | ```
|
372 |
|
373 | Binaries produced by the Swift build process must be generated for the correct platform architecture. This Docker command will compile Swift sources files using the relevant Swift environment.
|
374 |
|
375 | ```
|
376 | docker run --rm -it -v $(pwd):/swift-package openwhisk/swift3action bash -e -c "cd /swift-package && swift build -v -c release"
|
377 | ```
|
378 |
|
379 | ## Writing Functions - Binary
|
380 |
|
381 | OpenWhisk supports executing a compiled binary for the function handler. Using a Python wrapper, the file will be invoked within the `openwhisk/dockerskeleton` Docker container.
|
382 |
|
383 | The binary must be compiled for the correct platform architecture and only link to shared libraries installed in the `openwhisk/dockerskeleton` runtime.
|
384 |
|
385 | In the `serverless.yaml` file, the `handler` property is used to denote the binary file to upload.
|
386 |
|
387 | ```yaml
|
388 | functions:
|
389 | my_function:
|
390 | handler: bin_file
|
391 | runtime: binary
|
392 | ```
|
393 |
|
394 | ### Request Properties
|
395 |
|
396 | OpenWhisk executes the binary file for each request. Event parameters are streamed to `stdio` as a JSON object string.
|
397 |
|
398 | ### Function Return Values
|
399 |
|
400 | The handler must write a JSON object string with the response parameters to `stdout` before exiting.
|
401 |
|
402 | If you want to return an error message, return an object with an `error` property with the message.
|
403 |
|
404 | ## Custom Runtime Images
|
405 |
|
406 | OpenWhisk actions can use [custom Docker images as the runtime environment](https://medium.com/openwhisk/large-applications-on-openwhisk-bcf15bff94ec). This allows extra packages, libraries or tools to be pre-installed in the runtime environment. Using a custom runtime image, with extra libraries and dependencies built-in, is useful for overcoming the [maximum deployment size](https://github.com/apache/incubator-openwhisk/blob/master/docs/reference.md#system-limits) on actions.
|
407 |
|
408 | *Images must implement the [API used by the platform](http://jamesthom.as/blog/2017/01/16/openwhisk-docker-actions/) to interact with runtime environments. Images must also be available on Docker Hub. OpenWhisk does not support private Docker registries.*
|
409 |
|
410 | OpenWhisk publishes the [existing runtime images on Docker Hub](https://hub.docker.com/r/openwhisk/). Using these images in the `FROM` directive in the `Dockerfile` is an easy way to [create new images](https://docs.docker.com/engine/reference/commandline/build/) compatible with the platform.
|
411 |
|
412 | In the `serverless.yaml` file, the `image` property is used to denote the custom runtime image.
|
413 |
|
414 | ```yaml
|
415 | functions:
|
416 | my_function:
|
417 | handler: source.js
|
418 | runtime: nodejs
|
419 | image: dockerhub_user/image_name
|
420 | ```
|
421 |
|
422 | *Node.js, Swift, Python and Binary runtimes support using a custom image property.*
|
423 |
|
424 | ## Writing Functions - Docker
|
425 |
|
426 | OpenWhisk supports creating actions from public images on Docker Hub without handler files. These images are expected to support the platform API used to instantiate and invoke serverless functions.
|
427 |
|
428 | All necessary files for execution must be provided within the image. Local source files will not be uploaded to the runtime environment.
|
429 |
|
430 | In the `serverless.yaml` file, the `handler` property is used to denote the image label.
|
431 |
|
432 | ```yaml
|
433 | functions:
|
434 | my_function:
|
435 | handler: repo/image_name
|
436 | runtime: docker
|
437 | ```
|
438 |
|
439 | ## Runtime Configuration Properties
|
440 |
|
441 | The following OpenWhisk configuration properties are supported for functions defined in
|
442 | the `serverless.yaml` file.
|
443 |
|
444 | ```yaml
|
445 | functions:
|
446 | my_function:
|
447 | handler: file_name.handler_func
|
448 | runtime: 'runtime_label' // defaults to nodejs:default
|
449 | namespace: "..." // defaults to user-provided credentials
|
450 | memory: 256 // 128 to 512 (MB).
|
451 | timeout: 60 // 0.1 to 600 (seconds)
|
452 | parameters:
|
453 | foo: bar // default parameters
|
454 | anotations:
|
455 | foo: bar // action annotations
|
456 | ```
|
457 |
|
458 | ## Writing Sequences
|
459 |
|
460 | OpenWhisk supports a special type of serverless function called [sequences](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md#creating-action-sequences).
|
461 |
|
462 | These functions are defined from a list of other serverless functions. Upon invocation, the platform executes each function in series. Request parameters are passed into the first function in the list. Each subsequent function call is passed the output from the previous step as input parameters. The last function's return value is returned as the response result.
|
463 |
|
464 | Here's an example of the configuration to define a sequence function, composed of three other functions.
|
465 |
|
466 | ```yaml
|
467 | functions:
|
468 | my_function:
|
469 | sequence:
|
470 | - parse_input
|
471 | - do_some_algorithm
|
472 | - construct_output
|
473 | ```
|
474 |
|
475 | *Sequence functions do not have a handler file defined. If you want to refer to functions not defined in the serverless project, use the fully qualified identifier e.g. /namespace/package/action_name*
|
476 |
|
477 | ## Connecting HTTP Endpoints
|
478 |
|
479 | Functions can be bound to public URL endpoints using the [API Gateway service](https://github.com/openwhisk/openwhisk/blob/master/docs/apigateway.md). HTTP requests to configured endpoints will invoke functions on-demand. Requests parameters are passed as function arguments. Function return values are serialised as the JSON response body.
|
480 |
|
481 | HTTP endpoints for functions can be configured through the `serverless.yaml` file.
|
482 |
|
483 | ```yaml
|
484 | functions:
|
485 | my_function:
|
486 | handler: index.main
|
487 | events:
|
488 | - http: GET /api/greeting
|
489 | ```
|
490 |
|
491 | HTTP event configuration also supports using explicit parameters.
|
492 |
|
493 | - `method` - HTTP method (mandatory).
|
494 | - `path` - URI path for API gateway (mandatory).
|
495 | - `resp` - controls [web action content type](https://github.com/apache/incubator-openwhisk/blob/master/docs/webactions.md#additional-features), values include: `json`, `html`, `http`, `svg`or `text` (optional, defaults to `json`).
|
496 |
|
497 | ```yaml
|
498 | functions:
|
499 | my_function:
|
500 | handler: index.main
|
501 | events:
|
502 | - http:
|
503 | method: GET
|
504 | path: /api/http
|
505 | resp: http
|
506 | ```
|
507 |
|
508 | API Gateway hosts serving the API endpoints will be shown during deployment.
|
509 |
|
510 | ```shell
|
511 | $ serverless deploy
|
512 | ...
|
513 | endpoints:
|
514 | GET https://xxx-gws.api-gw.mybluemix.net/service_name/api/path --> service_name-dev-my_function
|
515 | ```
|
516 |
|
517 | Calling the configured API endpoints will execute the deployed functions.
|
518 |
|
519 | ````shell
|
520 | $ http get https://xxx-gws.api-gw.mybluemix.net/api/greeting?user="James Thomas"
|
521 | HTTP/1.1 200 OK
|
522 | Content-Type: application/json; charset=UTF-8
|
523 | Date: Mon, 19 Dec 2016 15:47:53 GMT
|
524 |
|
525 | {
|
526 | "message": "Hello James Thomas!"
|
527 | }
|
528 | ````
|
529 |
|
530 |
|
531 |
|
532 | ## Exporting Web Actions
|
533 |
|
534 | Functions can be turned into "*web actions*" which return HTTP content without use of an API Gateway. This feature is enabled by setting an annotation (`web-export`) in the configuration file.
|
535 |
|
536 | ```yaml
|
537 | functions:
|
538 | my_function:
|
539 | handler: index.main
|
540 | annotations:
|
541 | web-export: true
|
542 | ```
|
543 |
|
544 | Functions with this annotation can be invoked through a URL template with the following parameters.
|
545 |
|
546 | ```
|
547 | https://{APIHOST}/api/v1/experimental/web/{USER_NAMESPACE}/{PACKAGE}/{ACTION_NAME}.{TYPE}
|
548 | ```
|
549 |
|
550 | - *APIHOST* - platform endpoint e.g. *openwhisk.ng.bluemix.net.*
|
551 | - *USER_NAMESPACE* - this must be an explicit namespace and cannot use the default namespace (_).
|
552 | - PACKAGE - action package or `default`.
|
553 | - *ACTION_NAME* - default form `${servicename}-${space}-${name}`.
|
554 | - *TYPE* - `.json`, `.html`, `.text` or `.http`.
|
555 |
|
556 | Return values from the function are used to construct the HTTP response. The following parameters are supported.
|
557 |
|
558 | 1. `headers`: a JSON object where the keys are header-names and the values are string values for those headers (default is no headers).
|
559 | 2. `code`: a valid HTTP status code (default is 200 OK).
|
560 | 3. `body`: a string which is either plain text or a base64 encoded string (for binary data).
|
561 |
|
562 | Here is an example of returning HTML content:
|
563 |
|
564 | ```
|
565 | function main(args) {
|
566 | var msg = "you didn't tell me who you are."
|
567 | if (args.name) {
|
568 | msg = `hello ${args.name}!`
|
569 | }
|
570 | return {body:
|
571 | `<html><body><h3><center>${msg}</center></h3></body></html>`}
|
572 | }
|
573 | ```
|
574 |
|
575 | Here is an example of returning binary data:
|
576 |
|
577 | ```
|
578 | function main() {
|
579 | let png = <base 64 encoded string>
|
580 | return {
|
581 | headers: { "Content-Type": "image/png" },
|
582 | body: png };
|
583 | }
|
584 | ```
|
585 |
|
586 | Functions can access request parameters using the following environment variables.
|
587 |
|
588 | 1. `**__ow_meta_verb:**` the HTTP method of the request.
|
589 | 2. `**__ow_meta_headers:**` the request headers.
|
590 | 3. `**__ow_meta_path:**` the unmatched path of the request.
|
591 |
|
592 | Full details on this new feature are available in this [blog post](https://medium.com/openwhisk/serverless-http-handlers-with-openwhisk-90a986cc7cdd#.2x09176m8).
|
593 |
|
594 | _**IMPORTANT: [Web Actions](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md) is currently experimental and may be subject to breaking changes.**_
|
595 |
|
596 | ## Scheduled Invocations
|
597 |
|
598 | Functions can be set up to fire automatically using the [alarm package](https://github.com/openwhisk/openwhisk/blob/master/docs/catalog.md#using-the-alarm-package). This allows you to invoke functions with preset parameters at specific times (*12:00 each day*) or according to a schedule (*every ten minutes*).
|
599 |
|
600 | Scheduled invocation for functions can be configured through the `serverless.yaml` file.
|
601 |
|
602 | The `schedule` event configuration is controlled by a string, based on the UNIX crontab syntax, in the format `cron(X X X X X)`. This can either be passed in as a native string or through the `rate` parameter.
|
603 |
|
604 | ```yaml
|
605 | functions:
|
606 | my_function:
|
607 | handler: index.main
|
608 | events:
|
609 | - schedule: cron(* * * * *) // fires each minute.
|
610 | ```
|
611 |
|
612 | This above example generates a new trigger (`${service}_crawl_schedule_trigger`) and rule (`${service}_crawl_schedule_rule`) during deployment.
|
613 |
|
614 | Other `schedule` event parameters can be manually configured, e.g trigger or rule names.
|
615 |
|
616 | ```yaml
|
617 | functions:
|
618 | aggregate:
|
619 | handler: statistics.handler
|
620 | events:
|
621 | - schedule:
|
622 | rate: cron(0 * * * *) // call once an hour
|
623 | trigger: triggerName
|
624 | rule: ruleName
|
625 | max: 10000 // max invocations, default: 1000, max: 10000
|
626 | params: // event params for invocation
|
627 | hello: world
|
628 | ```
|
629 |
|
630 | ## IBM Message Hub Events
|
631 |
|
632 | IBM Bluemix provides an "Apache Kafka"-as-a-Service called IBM Message Hub. Functions can be connected to fire when messages arrive on Kafka topics.
|
633 |
|
634 | IBM Message Hub instances can be provisioned through the IBM Bluemix platform. OpenWhisk on Bluemix will export Message Hub service credentials bound to a package with the following name:
|
635 |
|
636 | ```
|
637 | /${BLUEMIX_ORG}_${BLUEMIX_SPACE}/Bluemix_${SERVICE_NAME}_Credentials-1
|
638 | ```
|
639 |
|
640 | Rather than having to manually define all the properties needed by the Message Hub trigger feed, you can reference a package to use instead. Credentials from the referenced package will be used when executing the trigger feed.
|
641 |
|
642 | Developers only need to add the topic to listen to for each trigger.
|
643 |
|
644 | ```yaml
|
645 | # serverless.yaml
|
646 | functions:
|
647 | index:
|
648 | handler: users.main
|
649 | events:
|
650 | - message_hub:
|
651 | package: /${BLUEMIX_ORG}_${BLUEMIX_SPACE}/Bluemix_${SERVICE_NAME}_Credentials-1
|
652 | topic: my_kafka_topic
|
653 |
|
654 | ```
|
655 |
|
656 | The plugin will create a trigger called `${serviceName}_${fnName}_messagehub_${topic}` and a rule called `${serviceName}_${fnName}_messagehub_${topic}_rule` to bind the function to the message hub events.
|
657 |
|
658 | The trigger and rule names created can be set explicitly using the `trigger` and`rule` parameters.
|
659 |
|
660 | Other functions can bind to the same trigger using the inline `trigger` event referencing this trigger name.
|
661 |
|
662 | ```yaml
|
663 | # serverless.yaml
|
664 | functions:
|
665 | index:
|
666 | handler: users.main
|
667 | events:
|
668 | - message_hub:
|
669 | package: /${BLUEMIX_ORG}_${BLUEMIX_SPACE}/Bluemix_${SERVICE_NAME}_Credentials-1
|
670 | topic: my_kafka_topic
|
671 | trigger: log_events
|
672 | rule: connect_index_to_kafka
|
673 | another:
|
674 | handler: users.another
|
675 | events:
|
676 | - trigger: log_events
|
677 | ```
|
678 |
|
679 | ### Using Manual Parameters
|
680 |
|
681 | Parameters for the Message Hub event source can be defined explicitly, rather than using pulling credentials from a package.
|
682 |
|
683 | ```yaml
|
684 | # serverless.yaml
|
685 | functions:
|
686 | index:
|
687 | handler: users.main
|
688 | events:
|
689 | - message_hub:
|
690 | topic: my_kafka_topic
|
691 | brokers: afka01-prod01.messagehub.services.us-south.bluemix.net:9093
|
692 | user: USERNAME
|
693 | password: PASSWORD
|
694 | admin_url: https://kafka-admin-prod01.messagehub.services.us-south.bluemix.net:443
|
695 | json: true
|
696 | binary_key: true
|
697 | binary_value: true
|
698 | ```
|
699 |
|
700 | `topic`, `brokers`, `user`, `password` and `admin_url` are mandatory parameters.
|
701 |
|
702 | ## Cloudant DB Events
|
703 |
|
704 | IBM Cloudant provides a hosted NoSQL database, based upon CouchDB, running on IBM Bluemix. Functions can be connected to events fired when the database is updated. These events use the [CouchDB changes feed](http://guide.couchdb.org/draft/notifications.html) to follow database modifications.
|
705 |
|
706 | IBM Cloudant instances can be provisioned through the IBM Bluemix platform. OpenWhisk on Bluemix will export Cloudant service credentials bound to a package with the following name:
|
707 |
|
708 | ```
|
709 | /${BLUEMIX_ORG}_${BLUEMIX_SPACE}/Bluemix_${SERVICE_NAME}_Credentials-1
|
710 | ```
|
711 |
|
712 | Rather than having to manually define all the properties needed by the [Cloudant trigger feed](https://github.com/openwhisk/openwhisk-package-cloudant#using-the-cloudant-package), you can reference a package to use instead. Credentials from the referenced package will be used when executing the trigger feed.
|
713 |
|
714 | Developers only need to add the database name to follow for modifications.
|
715 |
|
716 | ```yaml
|
717 | # serverless.yaml
|
718 | functions:
|
719 | index:
|
720 | handler: users.main
|
721 | events:
|
722 | - cloudant:
|
723 | package: /${BLUEMIX_ORG}_${BLUEMIX_SPACE}/Bluemix_${SERVICE_NAME}_Credentials-1
|
724 | db: my_db_name
|
725 |
|
726 | ```
|
727 |
|
728 | The plugin will create a trigger called `${serviceName}_${fnName}_cloudant_${topic}` and a rule called `${serviceName}_${fnName}_cloudant_${topic}_rule` to bind the function to the Cloudant update events.
|
729 |
|
730 | The trigger and rule names created can be set explicitly using the `trigger` and`rule` parameters.
|
731 |
|
732 | Other functions can bind to the same trigger using the inline `trigger` event referencing this trigger name.
|
733 |
|
734 | ### Using Manual Parameters
|
735 |
|
736 | Parameters for the Cloudant event source can be defined explicitly, rather than using pulling credentials from a package.
|
737 |
|
738 | ```yaml
|
739 | # serverless.yaml
|
740 | functions:
|
741 | index:
|
742 | handler: users.main
|
743 | events:
|
744 | - cloudant:
|
745 | host: xxx-yyy-zzz-bluemix.cloudant.com
|
746 | username: USERNAME
|
747 | password: PASSWORD
|
748 | db: db_name
|
749 | ```
|
750 |
|
751 | ### Adding Optional Parameters
|
752 |
|
753 | The following optional feed parameters are also supported:
|
754 |
|
755 | * `max` - Maximum number of triggers to fire. Defaults to infinite.
|
756 | * `filter` - Filter function defined on a design document.
|
757 | * `query` - Optional query parameters for the filter function.
|
758 |
|
759 | ```yaml
|
760 | # serverless.yaml
|
761 | functions:
|
762 | index:
|
763 | handler: users.main
|
764 | events:
|
765 | - cloudant:
|
766 | ...
|
767 | max: 10000
|
768 | query:
|
769 | status: new
|
770 | filter: mailbox/by_status
|
771 | ```
|
772 |
|
773 | ## Custom Event Triggers
|
774 |
|
775 | Functions are connected to event sources in OpenWhisk [using triggers and rules](https://github.com/openwhisk/openwhisk/blob/master/docs/triggers_rules.md). Triggers create a named event stream within the system. Triggers can be fired manually or connected to external data sources, like databases or message queues.
|
776 |
|
777 | Rules set up a binding between triggers and serverless functions. With an active rule, each time a trigger is fired, the function will be executed with the trigger payload.
|
778 |
|
779 | Event binding for functions can be configured through the `serverless.yaml` file.
|
780 |
|
781 | ```yaml
|
782 | functions:
|
783 | my_function:
|
784 | handler: index.main
|
785 | events:
|
786 | - trigger: my_trigger
|
787 | ```
|
788 | This configuration will create a trigger called `servicename-my_trigger` with an active rule binding `my_function` to this event stream.
|
789 |
|
790 | ### Customising Rules
|
791 |
|
792 | Rule names default to the following format `servicename-trigger-to-action`. These names be explicitly set through configuration.
|
793 |
|
794 | ```yaml
|
795 | functions:
|
796 | my_function:
|
797 | handler: index.main
|
798 | events:
|
799 | - trigger:
|
800 | name: "my_trigger"
|
801 | rule: "rule_name"
|
802 | ```
|
803 |
|
804 | ### Customing Triggers
|
805 |
|
806 | Triggers can be defined as separate resources in the `serverless.yaml` file. This allows you to set up trigger properties like default parameters.
|
807 |
|
808 | ```yaml
|
809 | functions:
|
810 | my_function:
|
811 | handler: index.main
|
812 | events:
|
813 | - trigger: my_trigger
|
814 |
|
815 | resources:
|
816 | triggers:
|
817 | my_trigger:
|
818 | parameters:
|
819 | hello: world
|
820 | ```
|
821 |
|
822 | ### Trigger Feeds
|
823 |
|
824 | Triggers can be bound to external event sources using the `feed` property. OpenWhisk [provides a catalogue](https://github.com/openwhisk/openwhisk/blob/master/docs/catalog.md) of third-party event sources bundled as [packages](https://github.com/openwhisk/openwhisk/blob/master/docs/packages.md#creating-and-using-trigger-feeds).
|
825 |
|
826 | This example demonstrates setting up a trigger which uses the `/whisk.system/alarms/alarm` feed. The `alarm` feed will fire a trigger according to a user-supplied cron schedule.
|
827 |
|
828 | ```yaml
|
829 | resources:
|
830 | triggers:
|
831 | alarm_trigger:
|
832 | parameters:
|
833 | hello: world
|
834 | feed: /whisk.system/alarms/alarm
|
835 | feed_parameters:
|
836 | cron: '*/8 * * * * *'
|
837 | ```
|
838 |
|
839 | ## Commands
|
840 |
|
841 | The following serverless commands are currently implemented for the OpenWhisk provider.
|
842 |
|
843 | - `deploy` - [Deploy functions, triggers and rules for service](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/deploy/).
|
844 | - `invoke`- [Invoke deployed serverless function and show result](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/invoke/).
|
845 | - `invokeLocal`- [Invoke serverless functions locally and show result](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/invoke#invoke-local).
|
846 | - `remove` - [Remove functions, triggers and rules for service](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/remove/).
|
847 | - `logs` - [Display activation logs for deployed function](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/logs/).
|
848 | - `info` - [Display details on deployed functions, triggers and rules](https://serverless.com/framework/docs/providers/openwhisk/cli-reference/info/).
|