diff --git a/.circleci/config.yml b/.circleci/config.yml index 409f872a4..30a3261ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,6 +29,8 @@ jobs: sudo service docker stop curl -fsSL https://get.docker.com/ | sudo sh - run: docker version + # login here for tests + - run: docker login -u $DOCKER_USER -p $DOCKER_PASS - run: ./test.sh - deploy: command: | @@ -36,6 +38,5 @@ jobs: git config --global user.email "ci@fnproject.com" git config --global user.name "CI" git branch --set-upstream-to=origin/${CIRCLE_BRANCH} ${CIRCLE_BRANCH} - docker login -u $DOCKER_USER -p $DOCKER_PASS ./release.sh fi diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 06503083e..15141eb83 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,13 +18,13 @@ before_script: build_job: stage: build script: - - go build -o functions-alpine + - make build build_job_fn: stage: build script: - cd fn - - go build -o fn-alpine + - make build formatting: stage: build diff --git a/cli/Makefile b/cli/Makefile index 40440f1db..981383638 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -16,7 +16,7 @@ dep-up: glide up -v test: - go test $(go list ./... | grep -v /vendor/ | grep -v /tests) + ./test.sh test-integration: cd tests/ && go test -v ./...; cd .. diff --git a/cli/client/call_fn.go b/cli/client/call_fn.go index 4bd4d0315..3b9bfe7b0 100644 --- a/cli/client/call_fn.go +++ b/cli/client/call_fn.go @@ -48,5 +48,10 @@ func CallFN(u string, content io.Reader, output io.Writer, method string, env [] io.Copy(output, resp.Body) + if resp.StatusCode >= 400 { + // TODO: parse out error message + return fmt.Errorf("error calling function: status %v", resp.StatusCode) + } + return nil } diff --git a/cli/langs/go.go b/cli/langs/go.go index 264ea80cc..e74f2f368 100644 --- a/cli/langs/go.go +++ b/cli/langs/go.go @@ -1,5 +1,11 @@ package langs +import ( + "io/ioutil" + "os" + "path/filepath" +) + type GoLangHelper struct { BaseHelper } @@ -38,3 +44,84 @@ func (h *GoLangHelper) DockerfileCopyCmds() []string { func (lh *GoLangHelper) Entrypoint() string { return "./func" } + +// HasPreBuild returns whether the Java runtime has boilerplate that can be generated. +func (lh *GoLangHelper) HasBoilerplate() bool { return true } + +// GenerateBoilerplate will generate function boilerplate for a Java runtime. The default boilerplate is for a Maven +// project. +func (lh *GoLangHelper) GenerateBoilerplate() error { + wd, err := os.Getwd() + if err != nil { + return err + } + codeFile := filepath.Join(wd, "func.go") + if exists(codeFile) { + return ErrBoilerplateExists + } + testFile := filepath.Join(wd, "test.json") + if exists(testFile) { + return ErrBoilerplateExists + } + + if err := ioutil.WriteFile(codeFile, []byte(helloGoSrcBoilerplate), os.FileMode(0644)); err != nil { + return err + } + + if err := ioutil.WriteFile(testFile, []byte(testBoilerPlate), os.FileMode(0644)); err != nil { + return err + } + return nil +} + +const ( + helloGoSrcBoilerplate = `package main + +import ( + "encoding/json" + "fmt" + "os" +) + +type Person struct { + Name string +} + +func main() { + p := &Person{Name: "World"} + json.NewDecoder(os.Stdin).Decode(p) + mapD := map[string]string{"message": fmt.Sprintf("Hello %s", p.Name)} + mapB, _ := json.Marshal(mapD) + fmt.Println(string(mapB)) +} +` + + // Could use same test for most langs + testBoilerPlate = `{ + "tests": [ + { + "input": { + "body": { + "name": "Johnny" + } + }, + "output": { + "body": { + "message": "Hello Johnny" + } + } + }, + { + "input": { + "body": "" + }, + "output": { + "body": { + "message": "Hello World" + } + } + } + ] +} +` +) diff --git a/cli/main.go b/cli/main.go index 96e6e56b0..ebd8ae484 100644 --- a/cli/main.go +++ b/cli/main.go @@ -37,8 +37,8 @@ func newFn() *cli.App { app.Name = "fn" app.Version = Version app.Authors = []cli.Author{{Name: "Oracle Corporation"}} - app.Description = "Oracle Functions command line tools" - app.UsageText = `Check the manual at https://github.com/fnproject/fn/blob/master/fn/README.md` + app.Description = "Fn command line tool" + app.UsageText = `Check the docs at https://github.com/fnproject/fn/blob/master/fn/README.md` cli.AppHelpTemplate = `{{.Name}} {{.Version}}{{if .Description}} @@ -129,7 +129,12 @@ func prepareCmdArgsValidation(cmds []cli.Command) { func main() { app := newFn() - app.Run(os.Args) + err := app.Run(os.Args) + if err != nil { + // TODO: this doesn't seem to get called even when an error returns from a command, but maybe urfave is doing a non zero exit anyways? nope: https://github.com/urfave/cli/issues/610 + fmt.Printf("Error occurred: %v, exiting...\n", err) + os.Exit(1) + } } func resetBasePath(c *functions.Configuration) error { diff --git a/cli/test.sh b/cli/test.sh new file mode 100755 index 000000000..5291f4e2d --- /dev/null +++ b/cli/test.sh @@ -0,0 +1,32 @@ +set -ex + +make build +export fn="$(pwd)/fn" +$fn --version + +go test $(go list ./... | grep -v /vendor/ | grep -v /tests) + +# This tests all the quickstart commands on the cli on a live server +rm -rf tmp +mkdir tmp +cd tmp +funcname="fn-test-go" +$fn init --runtime go $DOCKER_USER/$funcname +$fn test + +someport=50080 +docker rm --force functions || true # just in case +docker run --name functions -d -v /var/run/docker.sock:/var/run/docker.sock -p $someport:8080 funcy/functions +sleep 10 +docker logs functions + +export API_URL="http://localhost:$someport" +$fn apps l +$fn apps create myapp +$fn apps l +$fn deploy myapp +$fn call myapp $funcname + +docker rm --force functions + +cd .. diff --git a/examples/tutorial/hello/go/func.go b/examples/tutorial/hello/go/func.go index adaac4144..c1f3f8401 100644 --- a/examples/tutorial/hello/go/func.go +++ b/examples/tutorial/hello/go/func.go @@ -14,7 +14,6 @@ type Person struct { func main() { p := &Person{Name: "World"} json.NewDecoder(os.Stdin).Decode(p) - // fmt.Printf("Hello %v!\n", p.Name) mapD := map[string]string{"message": fmt.Sprintf("Hello %s", p.Name)} mapB, _ := json.Marshal(mapD) fmt.Println(string(mapB))