:warning: Work in progress :warning:
This is an OpenWhisk runtime for Golang and Generic executables.
You need a Linux or an OSX environment, with Java and Docker installed to build the sources.
Prerequisites for running build and tests with gradle:
To compile go proxy in amd64 architecture for docker:
./gradlew build
To build the docker images after compiling go proxy:
./gradlew distDocker
This will build the images:
actionloop-golang-v1.11
: an image supporting Go sourcesactionloop
: the base image, supporting generic executables ans shell scriptThe actionloop
image can be used for supporting other compiled programming languages as long as they implement a compile
script and the action loop protocol described below.
To run tests
./gradlew test --info
If you want to develop the proxy and run tests natively, you can on Linux or OSX. Tested on Ubuntu Linux (14.04) and OSX 10.13. Probably other distributions work, maybe even Windows with WSL, but since it is not tested YMMMV.
You need of course go 1.11.0
Then you need a set of utilities used in tests:
Linux: apt-get install bc zip realpath
OSX: brew install zip coreutils
NOTE: Because tests build and cache some binary files, perform a git clean -fx
and do not share folders between linux and osx because binaries are in different format...
The image can execute, compiling them on the fly, Golang OpenWhisk actions in source format.
An action must be a Go source file, placed in the main
package and your action.
Since main.main
is reserved in Golang for the entry point of your program, and the entry point is used by support code, your action must be named Main
(with capital M
) even if your specify main
as the name of the action (or you do not specify it, defaulting to main
). If you specify a function name different than main
the name of your functino does not need to be capitalized.
The expected signature for a main
function is:
func Main(event map[string]interface{}) map[string]interface{}
For example:
package main import "log" // Main is the function implementing the action func Main(obj map[string]interface{}) map[string]interface{} { // do your work name, ok := obj["name"].(string) if !ok { name = "Stranger" } msg := make(map[string]interface{}) msg["message"] = "Hello, " + name + "!" // log in stdout or in stderr log.Printf("name=%s\n", name) // encode the result back in json return msg }
You can also have multiple source files in an action. In this case you need to collect all the sources in a zip file for posting.
Compiling sources on the image can take some time when the images is initialised. You can speed up precompiling the sources using the image as an offline compiler. You need docker
for doing that.
The images accepts a -compile <main>
flag, and expects you provide sources in standard input. It will then compile them, emit the binary in standard output and errors in stderr.
If you have docker, you can do it this way:
If you have a single source maybe in file main.go
, with a function named Main
just do this:
cat main.go | docker run openwhisk/actionloop-golang-v1.11 -compile main >main
If you have multiple sources in current directory, even with a subfolder with sources, you can compile it all with:
zip -r - * | docker run openwhisk/actionloop-golang-v1.11 -compile main >main
The generated executable is suitable to be deployed in openwhisk:
wsk action create my/action main -docker openwhisk/actionloop-golang-v1.11
Note that the output is always in Linux AMS64 format so the executable can be run only inside a Docker Linux container.
The actionloop
image is designed to support generic linux executable in an efficient way.
As such it works with any executable that supports the following simple protocol:
Repeat forever:
"value": JSON, "namespace": String, "action_name": String, "api_host": String, "api_key": String, "activation_id": String, "deadline": Number }``` Note that if you use libraries, those will expect the values in enviroment variables: - `__OW_NAMESPACE` - `__OW_ACTION_NAME` - `__OW_API_HOST` - `__OW_API_KEYS` - `__OW_ACTIVATION_ID` - `__OW_DEADLINE` - execute the action, using the `value` that contains the payload provided by the used and logging in standard output and in standard error (file descriptor 1 and 2) - write an answer in json format as a single line (without embedding newlines - newlines in strings must be quoted) The `actionloop` image works actually with executable in unix sense, so also scripts are acceptable. In the actionloop image there is `bash` and the `jq` command, so you can for example implement the actionloop with a shell script: ```bash #!/bin/bash # read input forever line by line while read line do # parse the in input with `jq` name="$(echo $line | jq -r .name.value)" # log in stdout echo msg="hello $name" # produce the result - note the fd3 echo '{"hello": "'$name'"}' >&3 done
Note the actionloop
image will accept any source and will try to run it (if it is possible), while the actionloop-golang
images will try to compile the sources instead.