Update dependencies (#1278)

* Update deps and prune

* Use v1.3.1

* Update logrus

* Remove constaint for /x/net
This commit is contained in:
James Jeffrey
2018-10-19 15:46:51 -07:00
committed by GitHub
parent a53b6a6199
commit 12f3ec72b2
12160 changed files with 50465 additions and 6629844 deletions

View File

@@ -1,3 +0,0 @@
# Please refer to main contribution doc:
https://github.com/fnproject/fn/blob/master/CONTRIBUTING.md

View File

@@ -1,83 +0,0 @@
# Go Fn Development Kit (FDK)
[![GoDoc](https://godoc.org/github.com/fnproject/fdk-go?status.svg)](https://godoc.org/github.com/fnproject/fdk-go)
fdk-go provides convenience functions for writing Go fn code
For getting started with fn, please refer to https://github.com/fnproject/fn/blob/master/README.md
# Installing fdk-go
```sh
go get github.com/fnproject/fdk-go
```
or your favorite vendoring solution :)
# Examples
For a simple getting started, see the [examples](/examples/hello) and follow
the [README](/examples/README.md). If you already have `fn` set up it
will take 2 minutes!
# Advanced example
TODO going to move to [examples](examples/) too :)
```go
package main
import (
"context"
"fmt"
"io"
"encoding/json"
fdk "github.com/fnproject/fdk-go"
"net/http"
)
func main() {
fdk.Handle(fdk.HandlerFunc(myHandler))
}
func myHandler(ctx context.Context, in io.Reader, out io.Writer) {
fnctx := fdk.Context(ctx)
contentType := fnctx.Header.Get("Content-Type")
if contentType != "application/json" {
fdk.WriteStatus(out, 400)
fdk.SetHeader(out, "Content-Type", "application/json")
io.WriteString(out, `{"error":"invalid content type"}`)
return
}
if fnctx.Method != "PUT" {
fdk.WriteStatus(out, 404)
fdk.SetHeader(out, "Content-Type", "application/json")
io.WriteString(out, `{"error":"route not found"}`)
return
}
var person struct {
Name string `json:"name"`
}
json.NewDecoder(in).Decode(&person)
// you can write your own headers & status, if you'd like to
fdk.WriteStatus(out, 201)
fdk.SetHeader(out, "Content-Type", "application/json")
all := struct {
Name string `json:"name"`
Header http.Header `json:"header"`
Config map[string]string `json:"config"`
}{
Name: person.Name,
Header: fnctx.Header,
Config: fnctx.Config,
}
json.NewEncoder(out).Encode(&all)
}
```

View File

@@ -1,33 +0,0 @@
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.11.0
working_directory: ~/fdk-go
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run: docker version
- run: docker pull fnproject/fnserver
# installing Fn CLI and starting the Fn server
- run:
command: |
curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
- run:
command: fn build
working_directory: examples/hello
- deploy:
command: |
if [[ "${CIRCLE_BRANCH}" == "master" && -z "${CIRCLE_PR_REPONAME}" ]]; then
func_version=$(awk '/^version:/ { print $2; }' func.yaml)
printenv DOCKER_PASS | docker login -u ${DOCKER_USER} --password-stdin
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 tag "hello:${func_version}" "fnproject/fdk-go-hello:${func_version}"
docker tag "hello:${func_version}" "fnproject/fdk-go-hello:latest"
docker push "fnproject/fdk-go-hello:${func_version}"
docker push "fnproject/fdk-go-hello:latest"
fi
working_directory: examples/hello

View File

@@ -1,59 +0,0 @@
# Function Examples
The goal of the `fdk`'s are to make it just as easy to write a hot function as
it is a cold one. The best way to showcase this is with an example.
This is an example of a hot function using the fdk-go bindings. The [hot function
documentation](https://github.com/fnproject/fn/blob/master/docs/developers/hot-functions.md)
contains an analysis of how this example works under the hood. With any of the
examples provided here, you may use any format to configure your functions in
`fn` itself. Here we add instructions to set up functions with a 'hot' format.
### How to run the example
Install the CLI tool, start a Fn server and run `docker login` to login to
DockerHub. See the [front page](https://github.com/fnproject/fn) for
instructions.
Initialize the example with an image name you can access:
```sh
fn init --runtime docker --format http --name <DOCKERHUB_USER/image_name>
```
`--format json` will also work here, or if your functions already use json
then adding the fdk will be seamless.
Build and deploy the function to the Fn server (default localhost:8080)
```sh
fn deploy --app hot-app
```
Now call your function (may take a sec to pull image):
```sh
curl -X POST -d '{"name":"Clarice"}' http://localhost:8080/r/hot-app/hello
```
**Note** that this expects you were in a directory named 'hello' (where this
example lives), if this doesn't work, replace 'hello' with your `$PWD` from
the `deploy` command.
Then call it again to see how fast hot functions are!
### Details
If you poke around in the Dockerfile you'll see that we're simply adding the
file found in this directory, getting the `fdk-go` package to our workspace
and then building a binary and building an image with that binary. That then
gets deployed to dockerhub and fn.
For more robust projects, it's recommended to use a tool like `dep` or
`glide` to get dependencies such as the `fdk-go` into your functions.
Scoping out `func.go` you can see that the handler code only deals with input
and output, and doesn't have to deal with decoding the formatting from
functions (i.e. i/o is presented through `io.Writer` and `io.Reader`). This
makes it much easier to write hot functions.

View File

@@ -1,18 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "github.com/fnproject/fdk-go"
packages = [
".",
"utils"
]
revision = "c6ce6afbce0935ffdf0e228471406d0f966736a5"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "c55f0d3da5ec2e9e5c9a7c563702e4cf28513fa1aaea1c18664ca2cb7d726f89"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,25 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
branch = "master"
name = "github.com/fnproject/fdk-go"

View File

@@ -1,29 +0,0 @@
package main
import (
"context"
"encoding/json"
"fmt"
"io"
fdk "github.com/fnproject/fdk-go"
)
func main() {
fdk.Handle(fdk.HandlerFunc(myHandler))
}
type Person struct {
Name string `json:"name"`
}
func myHandler(ctx context.Context, in io.Reader, out io.Writer) {
p := &Person{Name: "World"}
json.NewDecoder(in).Decode(p)
msg := struct {
Msg string `json:"message"`
}{
Msg: fmt.Sprintf("Hello %s", p.Name),
}
json.NewEncoder(out).Encode(&msg)
}

View File

@@ -1,6 +0,0 @@
schema_version: 20180708
name: hello
version: 0.0.1
runtime: go
entrypoint: ./func
format: http-stream

View File

@@ -1,322 +0,0 @@
package fdk
import (
"bufio"
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httputil"
"os"
"strings"
"testing"
"github.com/fnproject/fdk-go/utils"
"time"
)
func echoHTTPHandler(_ context.Context, in io.Reader, out io.Writer) {
io.Copy(out, in)
WriteStatus(out, http.StatusTeapot+2)
SetHeader(out, "yo", "dawg")
}
func TestHandler(t *testing.T) {
inString := "yodawg"
var in bytes.Buffer
io.WriteString(&in, inString)
var out bytes.Buffer
echoHTTPHandler(utils.BuildCtx(), &in, &out)
if out.String() != inString {
t.Fatalf("this was supposed to be easy. strings no matchy: %s got: %s", inString, out.String())
}
}
func TestDefault(t *testing.T) {
inString := "yodawg"
var in bytes.Buffer
io.WriteString(&in, inString)
var out bytes.Buffer
utils.DoDefault(HandlerFunc(echoHTTPHandler), utils.BuildCtx(), &in, &out)
if out.String() != inString {
t.Fatalf("strings no matchy: %s got: %s", inString, out.String())
}
}
func JSONHandler(_ context.Context, in io.Reader, out io.Writer) {
var person struct {
Name string `json:"name"`
}
json.NewDecoder(in).Decode(&person)
if person.Name == "" {
person.Name = "world"
}
body := fmt.Sprintf("Hello %s!\n", person.Name)
SetHeader(out, "Content-Type", "application/json")
err := json.NewEncoder(out).Encode(body)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
}
func JSONWithStatusCode(_ context.Context, _ io.Reader, out io.Writer) {
SetHeader(out, "Content-Type", "application/json")
WriteStatus(out, 201)
}
func TestJSON(t *testing.T) {
req := &utils.JsonIn{
CallID: "someid",
Body: `{"name":"john"}`,
ContentType: "application/json",
Deadline: "2018-01-30T16:52:39.786Z",
Protocol: utils.CallRequestHTTP{
Type: "http",
RequestURL: "http://localhost:8080/r/myapp/yodawg",
Headers: http.Header{},
Method: "POST",
},
}
var in bytes.Buffer
err := json.NewEncoder(&in).Encode(req)
if err != nil {
t.Fatal("Unable to marshal request")
}
var out, buf bytes.Buffer
err = utils.DoJSONOnce(HandlerFunc(JSONHandler), utils.BuildCtx(), &in, &out, &buf, make(http.Header))
if err != nil {
t.Fatal("should not return error", err)
}
JSONOut := &utils.JsonOut{}
err = json.NewDecoder(&out).Decode(JSONOut)
if err != nil {
t.Fatal(err.Error())
}
if !strings.Contains(JSONOut.Body, "Hello john!") {
t.Fatalf("Output assertion mismatch. Expected: `Hello john!\n`. Actual: %v", JSONOut.Body)
}
if JSONOut.Protocol.StatusCode != 200 {
t.Fatalf("Response code must equal to 200, but have: %v", JSONOut.Protocol.StatusCode)
}
}
func TestFailedJSON(t *testing.T) {
dummyBody := "should fail with this"
in := strings.NewReader(dummyBody)
var out, buf bytes.Buffer
JSONOut := &utils.JsonOut{}
err := utils.DoJSONOnce(HandlerFunc(JSONHandler), utils.BuildCtx(), in, &out, &buf, make(http.Header))
if err != nil {
t.Fatal("should not return error", err)
}
err = json.NewDecoder(&out).Decode(JSONOut)
if err != nil {
t.Fatal(err.Error())
}
if JSONOut.Protocol.StatusCode != 500 {
t.Fatalf("Response code must equal to 500, but have: %v", JSONOut.Protocol.StatusCode)
}
}
func TestJSONEOF(t *testing.T) {
var in, out, buf bytes.Buffer
err := utils.DoJSONOnce(HandlerFunc(JSONHandler), utils.BuildCtx(), &in, &out, &buf, make(http.Header))
if err != io.EOF {
t.Fatal("should return EOF")
}
}
func TestJSONOverwriteStatusCodeAndHeaders(t *testing.T) {
var out, buf bytes.Buffer
req := &utils.JsonIn{
CallID: "someid",
Body: `{"name":"john"}`,
ContentType: "application/json",
Deadline: "2018-01-30T16:52:39.786Z",
Protocol: utils.CallRequestHTTP{
Type: "json",
RequestURL: "http://localhost:8080/r/myapp/yodawg",
Headers: http.Header{},
Method: "POST",
},
}
var in bytes.Buffer
err := json.NewEncoder(&in).Encode(req)
if err != nil {
t.Fatal("Unable to marshal request")
}
err = utils.DoJSONOnce(HandlerFunc(JSONWithStatusCode), utils.BuildCtx(), &in, &out, &buf, make(http.Header))
if err != nil {
t.Fatal("should not return error", err)
}
JSONOut := &utils.JsonOut{}
err = json.NewDecoder(&out).Decode(JSONOut)
if err != nil {
t.Fatal(err.Error())
}
if JSONOut.Protocol.StatusCode != 201 {
t.Fatalf("Response code must equal to 201, but have: %v", JSONOut.Protocol.StatusCode)
}
cType := JSONOut.Protocol.Headers.Get("Content-Type")
if !strings.Contains(cType, "application/json") {
t.Fatalf("Response content type should be application/json in this test, but have: %v", cType)
}
}
func TestHTTP(t *testing.T) {
// simulate fn writing us http requests...
bodyString := "yodawg"
in := HTTPreq(t, bodyString)
var out bytes.Buffer
ctx := utils.BuildCtx()
err := utils.DoHTTPOnce(HandlerFunc(echoHTTPHandler), ctx, in, &out, &bytes.Buffer{}, make(http.Header))
if err != nil {
t.Fatal("should not return error", err)
}
res, err := http.ReadResponse(bufio.NewReader(&out), nil)
if err != nil {
t.Fatal(err)
}
if res.StatusCode != http.StatusTeapot+2 {
t.Fatal("got wrong status code", res.StatusCode)
}
outBody, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatal(err)
}
if res.Header.Get("yo") != "dawg" {
t.Fatal("expected yo dawg header, didn't get it")
}
if string(outBody) != bodyString {
t.Fatal("strings no matchy for http", string(outBody), bodyString)
}
}
func TestHTTPEOF(t *testing.T) {
var in bytes.Buffer
var out bytes.Buffer
ctx := utils.BuildCtx()
err := utils.DoHTTPOnce(HandlerFunc(echoHTTPHandler), ctx, &in, &out, &bytes.Buffer{}, make(http.Header))
if err != io.EOF {
t.Fatal("should return EOF")
}
}
func HTTPreq(t *testing.T, bod string) io.Reader {
req, err := http.NewRequest("GET", "http://localhost:8080/r/myapp/yodawg", strings.NewReader(bod))
if err != nil {
t.Fatal(err)
}
byts, err := httputil.DumpRequestOut(req, true)
if err != nil {
t.Fatal(err)
}
return bytes.NewReader(byts)
}
func setupTestFromRequest(t *testing.T, data interface{}, contentType, nameTest string) {
req := &utils.CloudEventIn{
CloudEvent: utils.CloudEvent{
EventID: "someid",
Source: "fn-api",
EventType: "test-type",
EventTypeVersion: "1.0",
EventTime: time.Now(),
ContentType: contentType,
Data: data,
},
Extensions: utils.CloudEventInExtension{
Deadline: "2018-01-30T16:52:39.786Z",
Protocol: utils.CallRequestHTTP{
Type: "http",
RequestURL: "http://localhost:8080/r/myapp/yodawg",
Headers: http.Header{},
Method: "POST",
},
},
}
var in bytes.Buffer
err := json.NewEncoder(&in).Encode(req)
if err != nil {
t.Fatal("Unable to marshal request")
}
t.Log(in.String())
var out, buf bytes.Buffer
err = utils.DoCloudEventOnce(HandlerFunc(JSONHandler), utils.BuildCtx(),
&in, &out, &buf, make(http.Header))
if err != nil {
t.Fatal("should not return error", err)
}
t.Log(out.String())
ceOut := &utils.CloudEventOut{}
err = json.NewDecoder(&out).Decode(ceOut)
if err != nil {
t.Fatal(err.Error())
}
if ceOut.Extensions.Protocol.StatusCode != 200 {
t.Fatalf("Response code must equal to 200, but have: %v", ceOut.Extensions.Protocol.StatusCode)
}
var respData string
json.Unmarshal([]byte(ceOut.Data.(string)), &respData)
if respData != "Hello "+nameTest+"!\n" {
t.Fatalf("Output assertion mismatch. Expected: `Hello %v!\n`. Actual: %v", nameTest, ceOut.Data)
}
}
func TestCloudEventWithJSONData(t *testing.T) {
data := map[string]string{
"name": "John",
}
contentType := "application/json"
setupTestFromRequest(t, data, contentType, "John")
}
func TestCloudEventWithStringData(t *testing.T) {
data := `{"name":"John"}`
contentType := "text/plain"
setupTestFromRequest(t, data, contentType, "John")
}
func TestCloudEventWithPerfectlyValidJSONValue(t *testing.T) {
// https://tools.ietf.org/html/rfc7159#section-3
data := false
contentType := "application/json"
setupTestFromRequest(t, data, contentType, "world")
}

View File

@@ -81,33 +81,22 @@ func decapHeaders(ctx context.Context, r *http.Request) (_ context.Context, canc
// find things we need, and for http headers add them to the httph bucket
// TODO i guess it's a good idea to differentiate when it's an http gateway guy or not
for k, vs := range r.Header {
switch k {
case "Fn-Deadline":
deadline = vs[0]
case "Fn-Call-Id":
rctx.callId = vs[0]
case "Content-Type":
// just leave this one instead of deleting
default:
continue
}
if !strings.HasPrefix(k, "Fn-Http-") {
// XXX(reed): we need 2 header buckets on ctx, one for these and one for the 'original req' headers
// for now just nuke so the headers are clean...
continue
}
switch {
case k == "Fn-Deadline":
deadline = vs[0]
case k == "Fn-Call-Id":
rctx.callId = vs[0]
case k == "Content-Type":
rctx.HTTPHeader[k] = vs
case k == "Fn-Http-Request-Url":
rctx.RequestURL = vs[0]
case k == "Fn-Http-Method":
rctx.Method = vs[0]
case strings.HasPrefix(k, "Fn-Http-H-"):
for _, v := range vs {
rctx.HTTPHeader.Add(strings.TrimPrefix(k, "Fn-Http-H-"), v)
}
rctx.HTTPHeader[strings.TrimPrefix(k, "Fn-Http-H-")] = vs
default:
// XXX(reed): just delete it? how is it here? maybe log/panic
}
@@ -161,7 +150,7 @@ func sockPerm(phonySock, realSock string) {
log.Fatalln("error giving sock file a perm", err)
}
err = os.Link(phonySock, realSock)
err = os.Symlink(filepath.Base(phonySock),realSock)
if err != nil {
log.Fatalln("error linking fake sock to real sock", err)
}