As promised I released a first implementation of Go support using the technique 
I described before.

In short, a library implementing the proxy and serving both /run and /init, 
with the ability of replace itself with a new version.

Using the library, implementing a function in Go looks like this:

---
package main

import (
        "encoding/json"
        "fmt"

        "github.com/sciabarracom/openwhisk-runtime-go/openwhisk"
)

func hello(event json.RawMessage) (json.RawMessage, error) {
        // input and output
        var input struct{ Name string }
        var output struct {
                Greetings string `json:"greetings"`
        }
        // read the input event
        json.Unmarshal(event, &input)
        if input.Name != "" {
                // handle the event
                output.Greetings = "Hello, " + input.Name
                fmt.Println(output.Greetings)
                return json.Marshal(output)
        }
        return nil, fmt.Errorf("no name specified")
}

func main() {
        openwhisk.Start(ciao)
}
---

Actually in practice it is better to place the function in a separate package 
for implementing some tests, because apparently adding tests in the main 
package does not work.

Source code of the library is here:

https://github.com/sciabarracom/openwhisk-runtime-go

Here is a simple transcription of how it works and how I tested it.

First you build  a couple of executable, and for simplicity you also prepare 
the json payload for the init.

$ cd test
$ go build -o hello ../main/hello.go
$ go build -o ciao ../main/ciao.go
$ echo '{"value":{"binary":true,"code":"'$(base64 hello)'"}}' >hello.json
$ echo '{"value":{"binary":true,"code":"'$(base64 ciao)'"}}' >ciao.json

Now you can start the actual server

$ go run ../main/exec.go

Now the magic happens.

Default behaviour (no executable)

```
$ curl -XPOST http://localhost:8080/run -d '{"value":{"name":"Mike"}}'
{"error":"the action failed to locate a binary"}
```

Now post the `hello` handler and run it:

```
$ curl -XPOST http://localhost:8080/init -d @hello.json
OK
$ curl -XPOST http://localhost:8080/run -d '{"value":{"name":"Mike"}}'
{"greetings":"Hello, Mike"}
```

As you can see, the function changed and now it implements the "hello" handler.

But the replaced server is still able to run init so let's do it again, 
replacing with the "ciao" handler.


```
$ curl -XPOST http://localhost:8080/init -d @ciao.json
OK
$ curl -XPOST http://localhost:8080/run -d '{"value":{"name":"Mike"}}'
{"saluti":"Ciao, Mike"}
```

---

I want to say "thank you" to James Thomas, I basically copied his code for 
implementing the /run handler since it was ready, then I added my code for the 
/init. I also had to dig into the internals of the http Go package more than I 
expected.

Work is not yet complete, I have to manage the environment variables (stealing 
more code from James Thomas implementation), package in Docker, integrate in 
OpenWhisk. But definitely I believe looks like a promising start.

-- 
  Michele Sciabarra
  openwh...@sciabarra.com

Reply via email to