How to run a Go function with redis package on OpenWhisk? - go

I am having some troubles to run a golang package on OpenWhisk (IBM Cloud Functions).
I ran the following on my local computer and it works without any problems (go run sample.go):
package main
import (
"fmt"
"encoding/json"
"github.com/go-redis/redis"
)
func main() {
var redisClient *redis.Client = redis.NewClient(&redis.Options{
Addr: "...",
Password: "...",
DB: 0,
})
redisClient.Set("foo", "bar", 0)
defer redisClient.Close()
msg := map[string]string{"msg": ("Done !")}
res, _ := json.Marshal(msg)
fmt.Println(string(res))
}
But i didn't find any way to make it working on OpenWhisk. I ran the following:
GOOS=linux GOARCH=amd64 go build -o exec sample.go
zip exec.zip exec
bx wsk action update myfunction --native exec.zip
bx wsk action invoke myfunction -r
bx wsk activation logs --last --strip
"error": "The action did not return a dictionary."
"2018-02-21T01:21:05.962244788Z stdout: [Errno 2] No such file or
directory: '/action/exec'"
The problem is related to the github.com/go-redis/redis package, when i remove it and its code then the function is running well. I met the same problem with the mgo package (MongoDB)...
I am new in Golang so it may be obvious, but for now i am stuck :/

The binary in the zip file is dynamically linked against shared libraries not available on the platform.
Using file and ldd confirms this:
$ file exec
exec: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, not stripped
$ ldd exec
/lib64/ld-linux-x86-64.so.2 (0x7f3f63f10000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f3f63f10000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f3f63f10000)
Build a static binary or build a dynamically linked binary inside the Docker image used by the platform (openwhisk/dockerskeleton).
The file not found error is misleading but reported by bash when executing files with this issue.

"error": "The action did not return a dictionary."
This is an open wsk error message.
It means that you did not return a dictionary on stdout
below is a valid return as it returns a json object
{"error":"something broke!"}
below would be invalid
"something broke!"
suggestions: check to see if there is any errors when you build ( normally )
the file in your dropbox doesnt look like a binary file...I suggest checking you can build the binary first

Related

Every "go" command leads to a panic from a certain main.go

I've noticed that every go command has stopped working, due to a panic from a main.go in a particular module:
> go env
panic: required key FOO missing value
goroutine 1 [running]:
github.com/kelseyhightower/envconfig.MustProcess(...)
/Users/kurtpeek/go/pkg/mod/github.com/kelseyhightower/envconfig#v1.4.0/envconfig.go:233
main.main()
/Users/kurtpeek/go/pkg/mod/github.com/myorg/mymodule/go#v0.0.0-20210129234103-92f90e2df5c0/main.go:13 +0x314
where the 'offending' main go is similar to
package main
import (
"github.com/kelseyhightower/envconfig"
"github.pie.apple.com/someorg/somemodule/config"
)
func main() {
cfg := &config.Config{}
envconfig.MustProcess("", cfg)
}
I have no idea why a go env command should fail for this reason?
Your module is called github.com/myorg/mymodule/go, which means that the installed binary is called "go" (after the last path segment). This binary likely shadows the go tool depending on how your PATH is configured.
I suggest you change the module path to avoid this problem.
You might try to reinstall go as it seems that somehow the binary for go env command is replaced by a binary you were potentially trying to compile, possible reason could be you built the program in the directory containing the go tools. I recommend reinstalling go

iron fuctions: fn build for iron/go can't load package github.com/x/y

I am trying to run basic commands given in https://github.com/iron-io/functions.
I created a fuc.go and funct.yaml file successfully but when I try to execute fn build, I get below error:
Running prebuild command: docker run --rm -v /home/evr:/go/src/github.com/x/y -w /go/src/github.com/x/y iron/go:dev go build -o func
can't load package: package github.com/x/y: C source files not allowed when not using cgo or SWIG: swap_sll.c
error running docker build: exit status 1
I got the cause for the above issue
Actually it was looking for data directory of iron function which I had specified a specific path instead of ${PWD} and was executing fn build in another working dirctory. So have to execute fn build in that directory where data directory is present (specific path which I specified).

Stringer tool complains about wrong archive header

I am trying to use go generate/stringer (golang.org/x/tools/cmd/stringer) to generate String() methods on enums. I have problems, which I believe, are because of slightly different format of .a packages on different systems. I have this file:
package main
import (
"math/rand"
)
//go:generate stringer -type=Foo
type Foo int;
const (
FooPrime Foo = iota
FooBis
)
func main() {
//Just use rand anywhere, otherwise we get a compiler error
rand.Seed(1)
}
Now if I run go generate example.go on my machine everything is all right: foo_string.go is created. However, on a test machine I get:
stringer: checking package: example.go:4:2: could not import math/rand (reading export data: /usr/lib64/go/pkg/linux_amd64/math/rand.a: go archive is missing __.PKGDEF)
Now, after some digging in the code I think that I get this error, because on my machine rand.a has the following header:
!<arch>
__.PKGDEF 0 0 0 644 2051
`
while on test machine it has the following header:
!<arch>
__.PKGDEF/ 0 399 399 100644 2051
`
I think that the crucial difference is slash after PKGDEFF. gcimporter refuses to process .a file, if it doesn't have __.PKGDEF header.
To check this, I edited manually gcimporter/exportdata.go and changed one of the line from this:
if name != "__.PKGDEF"
to this:
if name != "__.PKGDEF" && name != "__.PKGDEF\"
After this change (and compiling and installing everything) I was able to run go generate on example.go.
My questions are: why do I get this problem and how do I get rid of it (other then manually editing external library)?
What I can see from the spec for openSUSE's packaging they are disabling reinstallation of the standard library at updates. __.PKGDEF is a Go specific informational section, and some linker OpenSUSE has used has simply produced incompatible output.
There's nothing you can do except install a healthy Go from the official source.

Cross compile net/http for distribution

I have build the following code in a docker container with the following architecture:
cat /proc/version
Linux version 3.16.7-tinycore64 (root#064f0e1ce709) (gcc version 4.7.2 (Debian 4.7.2-5) ) #1 SMP Tue Dec 16 23:03:39 UTC 2014
package main
import "fmt"
func main() {
fmt.Println("Hello")
}
The binary distributed, runs with no problem on a busybox container, with the same architecture without installing golang.
The problem
When I do the same for the following code:
package main
import (
"fmt"
"net/http"
)
const (
port = ":80"
)
var calls = 0
func HelloWorld(w http.ResponseWriter, r *http.Request) {
calls++
fmt.Fprintf(w, "Hello, world! You have called me %d times.\n", calls)
}
func init() {
fmt.Printf("Started server at http://localhost%v.\n", port)
http.HandleFunc("/", HelloWorld)
http.ListenAndServe(port, nil)
}
func main() {}
Then I get:
ash: ./hello_world: not found
I might be missing some dependencies - like "net/http"?
But I thought the go build would build all into the binaries.
This is for both go build & go install.
Any idea?
The answer is most probably the one described in this article.
Some critical parts of the standard library use CGO [...] if you cross-compile Go to Darwin or Linux your programs won’t use the system DNS resolver. They also can’t use the native host certificate store. They also can’t look up the user’s home directory, either.
And CGO links against some standard system interfaces by default, dynamically.
The article suggests using gonative to fix the problem. If that's not your cup of tea, some people suggest using:
go build -ldflags "-linkmode external -extldflags -static"
Also read: https://groups.google.com/d/topic/golang-nuts/H-NTwhQVp-8/discussion
I think you need to disable cgo and build with netgo flag :
The net package requires cgo by default because the host operating
system must in general mediate network call setup. On some systems,
though, it is possible to use the network without cgo, and useful to
do so, for instance to avoid dynamic linking. The new build tag netgo
(off by default) allows the construction of a net package in pure Go
on those systems where it is possible.
The netgo tag requires version 1.2 and above.

How can I compile a Go program?

I got Go to compile:
0 known bugs; 0 unexpected bugs
and typed in the "hello world":
package main
import "fmt"
func main() {
fmt.Printf("Hello, 世界\n")
}
Then I tried to compile it, but it wouldn't go:
$ 8c gotest2
gotest2:1 not a function
gotest2:1 syntax error, last name: main
This is going on on Ubuntu Linux on Pentium. Go installed and passed its tests. So where did I go wrong? Can someone tell me where to go from here?
I also tried this program:
package main
import fmt "fmt" // Package implementing formatted I/O.
func main() {
fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n");
}
But this was also no go (must stop making go puns):
$ 8c gotest3.go
gotest3.go:1 not a function
gotest3.go:1 syntax error, last name: main
For Go 1.0+ the correct build command is now: go build
You're using 8c, which is the c compiler. 8g will compile go, and 8l will link.
(Update for Go1.0.x)
The section "Compile packages and dependencies" now list go build as the way to compile in go.
You still call 8g behind the scene, and the parameters you could pass to 8g are now passed with -gcflags.
-gcflags 'arg list'
arguments to pass on each 5g, 6g, or 8g compiler invocation
use go run to run the go program. Here is the output.
$ cat testgo.go
package main
import "fmt"
func main() {
fmt.Printf("Hello, 世界\n")
}
$go run testgo.go
Hello, 世界
To compile Go code, use the following commands:
go tool compile gotest3.go # To create an object file.
go tool link -o gotest3 gotest3.o # To compile from the object file.
chmod +x gotest3 # To apply executable flag.
./gotest3 # To run the binary.

Resources