rabbah commented on a change in pull request #4093: changes to include gloang runtime URL: https://github.com/apache/incubator-openwhisk/pull/4093#discussion_r230253870
########## File path: docs/actions-go.md ########## @@ -17,67 +17,185 @@ # --> -## Creating and invoking Go actions - -Using OpenWhisk [native actions](actions-docker.md#creating-native-actions), -you can package any executable as an action. This works for Go as an example. -As with [Docker actions](actions-docker.md), the Go executable receives a single argument -from the command line. -It is a string serialization of the JSON object representing the arguments to the action. -The program may log to `stdout` or `stderr`. -By convention, the last line of output _must_ be a stringified JSON object which represents -the result of the action. - -Here is an example Go action. +<a name="golang"/> + +# Creating and Invoking Go Actions + +The runtime `actionloop-golang-v1.11` runtime can execute actions written in the Go programming language in OpenWhisk, either as precompiled binary or compiling sources on the fly. + +## Entry Point + +The source code of an action is one or more Go source file. The entry point of the action is a function, placed in the `main` package. The default name for the main function is `Main`, but you can change it to any name you want using the `--main` switch in `wsk`. The name is however always capitalized. The function must have a specific signature, as described next. + +*NOTE* The runtime does *not* support different packages from `main` for the entry point. If you specify `hello.main` the runtime will try to use `Hello.main`, that will be almost certainly incorrect. You can however have other packages in your sources, as described below. + +## Signature + +The expected signature for a `main` function is: + +`func Main(event map[string]interface{}) map[string]interface{}` + +So a very simple single file `hello.go` action would be: + ```go package main -import "encoding/json" -import "fmt" -import "os" +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 = "world" + } + 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 +} +``` -func main() { - //program receives one argument: the JSON object as a string - arg := os.Args[1] +You can deploy it with just: - // unmarshal the string to a JSON object - var obj map[string]interface{} - json.Unmarshal([]byte(arg), &obj) +``` +wsk action create hello-go hello.go +``` - // can optionally log to stdout (or stderr) - fmt.Println("hello Go action") +You can also have multiple source files in an action, packages and vendor folders. - name, ok := obj["name"].(string) - if !ok { name = "Stranger" } +## Deployment + +The runtime `actionloop-golang-v1.11` accepts: + +- executable binaries in Linux ELF executable compiled for the AMD64 architecture +- zip files containing a binary executable named `exec` at the top level, again a Linux ELF executable compiled for the AMD64 architecture +- a single file source code in Go language, that will be compiled +- a zip file not containing in the top level a binary file `exec`, it will be interpreted as a collection of zip files, and compiled + +## Using packages and vendor folder + +When you deploy a zip file, you can: + +- have all your functions in the `main` package +- have some functions placed in some packages, like `hello` +- have some third party dependencies you want to include in your sources + +If all your functions are in the main package, just place all your sources in the top level of your zip file. + +### Use a package folder + +If some functions belongs to a package, like `hello/`, you need to be careful with the layout of your sources, especially if you use editors like [VcCode](#vscode), and make. The layout recommended is the following: - // last line of stdout is the result JSON object as a string - msg := map[string]string{"msg": ("Hello, " + name + "!")} - res, _ := json.Marshal(msg) - fmt.Println(string(res)) -} ``` +golang-main-package/ +- Makefile +- src/ + - main.go + - main_test.go + - hello/ + - hello.go + - hello_test.go +``` + +For running tests, editing without errors with package resolution, you need to use a `src` folder, place the sources that belongs to the main package in the `src` and place sources of your package in the `src/hello` folder. + +You should import it your subpackage with `import "hello"`. +Note this means if you want to compile locally you have to set your `GOPATH` to parent directory of your `src` directory. If you use VSCode, you need to enable the `go.inferGopath` option. + +When you send the sources, you will have to zip the content of the `src` folder, *not* the main directory. For example: -Save the code above to a file `sample.go` and cross compile it for OpenWhisk. -The executable must be called `exec`. -```bash -GOOS=linux GOARCH=amd64 go build -o exec -zip exec.zip exec -wsk action create helloGo --native exec.zip +``` +cd src +zip -r ../hello.zip * +cd .. +wsk action create hello2-go hello.zip --kind go:1.11 Review comment: I think the action names can just be hello to avoid the unnecessary hyphe. Easier to read. Maybe instead of hello2 it’s hellozip ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services