Skip to content

Commit

Permalink
grand Go SDK update (#1165)
Browse files Browse the repository at this point in the history
* grand Go SDK update

- Add `outbound-redis` set operations and `execute` function
- Add `key-value` support
- Remove `*_free` calls since they were buggy and unnecessary given that we tell `tinygo` to leak anyway
- Remove `-wasm-abi=generic` option since it's been removed as of `tinygo` 0.27

Signed-off-by: Joel Dice <[email protected]>

* fix Go CI issues

- Update Go and `tinygo` versions
- Use `interface{}` instead of `any` for broader compatibility
- Make `tinygo-outbound-redis` example sort the `SMEMBERS` result before comparing with the expected value

Signed-off-by: Joel Dice <[email protected]>

* rename Go SDK key-value directory to key_value

Signed-off-by: Joel Dice <[email protected]>

---------

Signed-off-by: Joel Dice <[email protected]>
  • Loading branch information
dicej authored Feb 16, 2023
1 parent 12596f3 commit 49721f2
Show file tree
Hide file tree
Showing 35 changed files with 1,224 additions and 61 deletions.
8 changes: 4 additions & 4 deletions .github/actions/spin-ci-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ inputs:
type: bool
golang-version:
description: 'golang version to setup'
default: '1.17'
default: '1.20'
required: false
type: string

Expand All @@ -82,10 +82,10 @@ inputs:
description: 'setup tinygo'
required: false
default: 'false'
type: bool
type: bool
tinygo-version:
description: 'tinygo version to setup'
default: 'v0.22.0'
default: 'v0.27.0'
required: false
type: string

Expand Down Expand Up @@ -150,4 +150,4 @@ runs:
uses: rajatjindal/setup-actions/[email protected]
if: ${{ inputs.tinygo == 'true' }}
with:
version: ${{ inputs.tinygo-version }}
version: ${{ inputs.tinygo-version }}
2 changes: 1 addition & 1 deletion examples/config-tinygo/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ route = "/..."
[component.config]
message = "I'm a {{object}}"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
4 changes: 2 additions & 2 deletions examples/http-tinygo-outbound-http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Building this as a WebAssembly module can be done using the `tinygo` compiler:

```shell
$ spin build
Executing the build command for component tinygo-hello: tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go
Executing the build command for component tinygo-hello: tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go
Successfully ran the build command for the Spin components.
```

Expand All @@ -44,7 +44,7 @@ allowed_http_hosts = [ "https://some-random-api.ml", "https://postman-echo.com"
[component.trigger]
route = "/hello"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
```

At this point, we can execute the application with the `spin` CLI:
Expand Down
2 changes: 1 addition & 1 deletion examples/http-tinygo-outbound-http/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ allowed_http_hosts = ["https://some-random-api.ml", "https://postman-echo.com"]
[component.trigger]
route = "/hello"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
4 changes: 2 additions & 2 deletions examples/http-tinygo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Building this as a WebAssembly module can be done using the `tinygo` compiler:

```shell
$ spin build
Executing the build command for component tinygo-hello: tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go
Executing the build command for component tinygo-hello: tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go
Successfully ran the build command for the Spin components.
```

Expand All @@ -52,7 +52,7 @@ source = "main.wasm"
[component.trigger]
route = "/hello"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
```

At this point, we can execute the application with the `spin` CLI:
Expand Down
2 changes: 1 addition & 1 deletion examples/http-tinygo/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ source = "main.wasm"
[component.trigger]
route = "/hello"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
14 changes: 14 additions & 0 deletions examples/tinygo-key-value/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Spin component in TinyGo

```shell
$ RUST_LOG=spin=trace spin build --up
```

The application can now receive requests on `http://localhost:3000/test`:

```shell
$ curl -i localhost:3000/test
HTTP/1.1 200 OK
content-length: 67
date: Tue, 29 Nov 2022 07:03:52 GMT
```
7 changes: 7 additions & 0 deletions examples/tinygo-key-value/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module github.com/fermyon/spin/templates/spin-http-tinygo-key-value

go 1.17

require github.com/fermyon/spin/sdk/go v0.0.0

replace github.com/fermyon/spin/sdk/go v0.0.0 => ../../sdk/go/
74 changes: 74 additions & 0 deletions examples/tinygo-key-value/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main

import (
"net/http"
"reflect"
"fmt"

spin_http "github.com/fermyon/spin/sdk/go/http"
"github.com/fermyon/spin/sdk/go/key_value"
)

func init() {

// handler for the http trigger
spin_http.Handle(func(w http.ResponseWriter, r *http.Request) {
store, err := key_value.Open("default");
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

defer key_value.Close(store)

if err := key_value.Set(store, "foo", []byte("bar")); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

{
expected := []byte("bar")
if value, err := key_value.Get(store, "foo"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if !reflect.DeepEqual(value, expected) {
http.Error(
w,
fmt.Sprintf("expected %v, got %v", expected, value),
http.StatusInternalServerError,
)
return
}
}

{
expected := []string{"foo"}
if value, err := key_value.GetKeys(store); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if !reflect.DeepEqual(value, expected) {
http.Error(
w,
fmt.Sprintf("expected %v, got %v", expected, value),
http.StatusInternalServerError,
)
return
}
}

if err := key_value.Delete(store, "foo"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

if exists, err := key_value.Exists(store, "foo"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if exists {
http.Error(w, "key was not deleted as expected", http.StatusInternalServerError)
return
}
})
}

func main() {}
14 changes: 14 additions & 0 deletions examples/tinygo-key-value/spin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
spin_version = "1"
authors = ["Fermyon Engineering <[email protected]>"]
name = "tinygo-key-value-example"
trigger = { type = "http", base = "/" }
version = "0.1.0"

[[component]]
id = "key-value"
source = "main.wasm"
key_value_stores = ["default"]
[component.trigger]
route = "/test"
[component.build]
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
2 changes: 2 additions & 0 deletions examples/tinygo-outbound-redis/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ go 1.17

require github.com/fermyon/spin/sdk/go v0.0.0

require golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect

replace github.com/fermyon/spin/sdk/go v0.0.0 => ../../sdk/go/
2 changes: 2 additions & 0 deletions examples/tinygo-outbound-redis/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
82 changes: 82 additions & 0 deletions examples/tinygo-outbound-redis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"net/http"
"os"
"strconv"
"reflect"
"fmt"

"golang.org/x/exp/slices"
spin_http "github.com/fermyon/spin/sdk/go/http"
"github.com/fermyon/spin/sdk/go/redis"
)
Expand Down Expand Up @@ -39,6 +42,7 @@ func init() {
// get redis payload for `mykey`
if payload, err := redis.Get(addr, "mykey"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else {
w.Write([]byte("mykey value was: "))
w.Write(payload)
Expand All @@ -48,6 +52,7 @@ func init() {
// incr `spin-go-incr` by 1
if payload, err := redis.Incr(addr, "spin-go-incr"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else {
w.Write([]byte("spin-go-incr value: "))
w.Write([]byte(strconv.FormatInt(payload, 10)))
Expand All @@ -62,6 +67,83 @@ func init() {
w.Write([]byte(strconv.FormatInt(payload, 10)))
w.Write([]byte("\n"))
}

if _, err := redis.Sadd(addr, "myset", []string{"foo", "bar"}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

{
expected := []string{"bar", "foo"}
payload, err := redis.Smembers(addr, "myset")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
slices.Sort(payload)
if !reflect.DeepEqual(payload, expected) {
http.Error(
w,
fmt.Sprintf(
"unexpected SMEMBERS result: expected %v, got %v",
expected,
payload,
),
http.StatusInternalServerError,
)
return
}
}

if _, err := redis.Srem(addr, "myset", []string{"bar"}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

{
expected := []string{"foo"}
if payload, err := redis.Smembers(addr, "myset"); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if !reflect.DeepEqual(payload, expected) {
http.Error(
w,
fmt.Sprintf(
"unexpected SMEMBERS result: expected %v, got %v",
expected,
payload,
),
http.StatusInternalServerError,
)
return
}
}

message := redis.RedisParameter{Kind: redis.RedisParameterKindBinary, Val: []byte("message")}
hello := redis.RedisParameter{Kind: redis.RedisParameterKindBinary, Val: []byte("hello")}
if _, err := redis.Execute(addr, "set", []redis.RedisParameter{message, hello}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

world := redis.RedisParameter{Kind: redis.RedisParameterKindBinary, Val: []byte(" world")}
if _, err := redis.Execute(addr, "append", []redis.RedisParameter{message, world}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

if payload, err := redis.Execute(addr, "get", []redis.RedisParameter{message}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} else if !reflect.DeepEqual(
payload,
[]redis.RedisResult{redis.RedisResult{
Kind: redis.RedisResultKindBinary,
Val: []byte("hello world"),
}}) {
http.Error(w, "unexpected GET result", http.StatusInternalServerError)
return
}
})
}

Expand Down
2 changes: 1 addition & 1 deletion examples/tinygo-outbound-redis/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ environment = { REDIS_ADDRESS = "redis://127.0.0.1:6379", REDIS_CHANNEL = "messa
[component.trigger]
route = "/publish"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
2 changes: 1 addition & 1 deletion examples/tinygo-redis/spin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ source = "main.wasm"
[component.trigger]
channel = "messages"
[component.build]
command = "tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
19 changes: 13 additions & 6 deletions sdk/go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
# ----------------------------------------------------------------------
.PHONY: test
test: test-integration
tinygo test -wasm-abi=generic -target=wasi -gc=leaking -v ./http
tinygo test -wasm-abi=generic -target=wasi -gc=leaking -v ./redis
tinygo test -target=wasi -gc=leaking -v ./http
tinygo test -target=wasi -gc=leaking -v ./redis

.PHONY: test-integration
test-integration: http/testdata/http-tinygo/main.wasm
go test -v -count=1 .

http/testdata/http-tinygo/main.wasm: generate
http/testdata/http-tinygo/main.wasm: http/testdata/http-tinygo/main.go
tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o http/testdata/http-tinygo/main.wasm http/testdata/http-tinygo/main.go
tinygo build -target=wasi -gc=leaking -no-debug -o http/testdata/http-tinygo/main.wasm http/testdata/http-tinygo/main.go

# ----------------------------------------------------------------------
# Build examples
Expand All @@ -26,9 +26,10 @@ build-examples: $(EXAMPLES_DIR)/http-tinygo-outbound-http/main.wasm
build-examples: $(EXAMPLES_DIR)/http-tinygo/main.wasm
build-examples: $(EXAMPLES_DIR)/tinygo-outbound-redis/main.wasm
build-examples: $(EXAMPLES_DIR)/tinygo-redis/main.wasm
build-examples: $(EXAMPLES_DIR)/tinygo-key-value/main.wasm

$(EXAMPLES_DIR)/%/main.wasm: $(EXAMPLES_DIR)/%/main.go
tinygo build -wasm-abi=generic -target=wasi -gc=leaking -no-debug -o $@ $<
tinygo build -target=wasi -gc=leaking -no-debug -o $@ $<

# ----------------------------------------------------------------------
# Generate C bindings
Expand All @@ -38,11 +39,12 @@ GENERATED_OUTBOUND_HTTP = http/wasi-outbound-http.c http/wasi-outbound-http.h
GENERATED_SPIN_HTTP = http/spin-http.c http/spin-http.h
GENERATED_OUTBOUND_REDIS = redis/outbound-redis.c redis/outbound-redis.h
GENERATED_SPIN_REDIS = redis/spin-redis.c redis/spin-redis.h
GENERATED_KEY_VALUE = key_value/key-value.c key_value/key-value.h

.PHONY: generate
generate: $(GENERATED_OUTBOUND_HTTP) $(GENERATED_SPIN_HTTP)
generate: $(GENERATED_OUTBOUND_REDIS) $(GENERATED_SPIN_REDIS)
generate: $(GENERATED_SPIN_CONFIG)
generate: $(GENERATED_SPIN_CONFIG) $(GENERATED_KEY_VALUE)

$(GENERATED_SPIN_CONFIG):
wit-bindgen c --import ../../wit/ephemeral/spin-config.wit --out-dir ./config
Expand All @@ -59,16 +61,21 @@ $(GENERATED_OUTBOUND_REDIS):
$(GENERATED_SPIN_REDIS):
wit-bindgen c --export ../../wit/ephemeral/spin-redis.wit --out-dir ./redis

$(GENERATED_KEY_VALUE):
wit-bindgen c --import ../../wit/ephemeral/key-value.wit --out-dir ./key_value

# ----------------------------------------------------------------------
# Cleanup
# ----------------------------------------------------------------------
.PHONY: clean
clean:
rm -rf $(GENERATED_SPIN_CONFIG)
rm -f $(GENERATED_SPIN_CONFIG)
rm -f $(GENERATED_OUTBOUND_HTTP) $(GENERATED_SPIN_HTTP)
rm -f $(GENERATED_OUTBOUND_REDIS) $(GENERATED_SPIN_REDIS)
rm -f $(GENERATED_KEY_VALUE)
rm -f http/testdata/http-tinygo/main.wasm
rm -f $(EXAMPLES_DIR)/http-tinygo/main.wasm
rm -f $(EXAMPLES_DIR)/http-tinygo-outbound-http/main.wasm
rm -f $(EXAMPLES_DIR)/tinygo-outbound-redis/main.wasm
rm -f $(EXAMPLES_DIR)/tinygo-redis/main.wasm
rm -f $(EXAMPLES_DIR)/tinygo-key-value/main.wasm
Loading

0 comments on commit 49721f2

Please sign in to comment.