mirror of
https://github.com/openfaas/faas.git
synced 2025-06-18 12:06:37 +00:00
Merge master into breakout_swarm
Signed-off-by: Alex Ellis <alexellis2@gmail.com>
This commit is contained in:
17
gateway/vendor/github.com/openfaas/nats-queue-worker/.gitignore
generated
vendored
Normal file
17
gateway/vendor/github.com/openfaas/nats-queue-worker/.gitignore
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Go
|
||||
.glide/
|
||||
.idea
|
||||
.DS_Store
|
||||
|
17
gateway/vendor/github.com/openfaas/nats-queue-worker/.travis.yml
generated
vendored
Normal file
17
gateway/vendor/github.com/openfaas/nats-queue-worker/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
sudo: required
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.9.x
|
||||
install:
|
||||
- echo "Please don't go get"
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_script:
|
||||
- curl -sSL test.docker.com | sudo -E sh
|
||||
|
||||
script:
|
||||
- cd queue-worker && ./build.sh
|
9
gateway/vendor/github.com/openfaas/nats-queue-worker/CONTRIBUTING.md
generated
vendored
Normal file
9
gateway/vendor/github.com/openfaas/nats-queue-worker/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
## Contributing
|
||||
|
||||
### License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
|
||||
## Guidelines
|
||||
|
||||
See guide for [FaaS](https://github.com/openfaas/faas/blob/master/CONTRIBUTING.md) here.
|
1
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/.gitignore
generated
vendored
Normal file
1
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
queue-worker
|
19
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/Dockerfile
generated
vendored
Normal file
19
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/Dockerfile
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
FROM golang:1.9.2-alpine as golang
|
||||
WORKDIR /go/src/github.com/openfaas/nats-queue-worker
|
||||
|
||||
COPY vendor vendor
|
||||
COPY main.go .
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
|
||||
|
||||
FROM alpine:3.6
|
||||
RUN apk add --no-cache ca-certificates
|
||||
WORKDIR /root/
|
||||
|
||||
EXPOSE 8080
|
||||
ENV http_proxy ""
|
||||
ENV https_proxy ""
|
||||
|
||||
COPY --from=golang /go/src/github.com/openfaas/nats-queue-worker/app .
|
||||
|
||||
CMD ["./app"]
|
19
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/Dockerfile.armhf
generated
vendored
Normal file
19
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/Dockerfile.armhf
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
FROM golang:1.9.2-alpine as golang
|
||||
WORKDIR /go/src/github.com/openfaas/nats-queue-worker
|
||||
|
||||
COPY vendor vendor
|
||||
COPY main.go .
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
|
||||
|
||||
FROM alpine:3.6
|
||||
RUN apk add --no-cache ca-certificates
|
||||
WORKDIR /root/
|
||||
|
||||
EXPOSE 8080
|
||||
ENV http_proxy ""
|
||||
ENV https_proxy ""
|
||||
|
||||
COPY --from=golang /go/src/github.com/openfaas/nats-queue-worker/app .
|
||||
|
||||
CMD ["./app"]
|
12
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/build.sh
generated
vendored
Executable file
12
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/build.sh
generated
vendored
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
export eTAG="latest-dev"
|
||||
echo $1
|
||||
if [ $1 ] ; then
|
||||
eTAG=$1
|
||||
fi
|
||||
|
||||
echo Building functions/queue-worker:$eTAG
|
||||
|
||||
docker build --build-arg http_proxy=$http_proxy -t functions/queue-worker:$eTAG .
|
||||
|
288
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/main.go
generated
vendored
Normal file
288
gateway/vendor/github.com/openfaas/nats-queue-worker/queue-worker/main.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/nats-io/go-nats-streaming"
|
||||
"github.com/openfaas/faas/gateway/queue"
|
||||
)
|
||||
|
||||
// AsyncReport is the report from a function executed on a queue worker.
|
||||
type AsyncReport struct {
|
||||
FunctionName string `json:"name"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
TimeTaken float64 `json:"timeTaken"`
|
||||
}
|
||||
|
||||
func printMsg(m *stan.Msg, i int) {
|
||||
log.Printf("[#%d] Received on [%s]: '%s'\n", i, m.Subject, m)
|
||||
}
|
||||
|
||||
func makeClient() http.Client {
|
||||
proxyClient := http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 0,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 1,
|
||||
DisableKeepAlives: true,
|
||||
IdleConnTimeout: 120 * time.Millisecond,
|
||||
ExpectContinueTimeout: 1500 * time.Millisecond,
|
||||
},
|
||||
}
|
||||
return proxyClient
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
|
||||
clusterID := "faas-cluster"
|
||||
val, _ := os.Hostname()
|
||||
clientID := "faas-worker-" + val
|
||||
|
||||
natsAddress := "nats"
|
||||
gatewayAddress := "gateway"
|
||||
functionSuffix := ""
|
||||
var debugPrintBody bool
|
||||
|
||||
if val, exists := os.LookupEnv("faas_nats_address"); exists {
|
||||
natsAddress = val
|
||||
}
|
||||
|
||||
if val, exists := os.LookupEnv("faas_gateway_address"); exists {
|
||||
gatewayAddress = val
|
||||
}
|
||||
|
||||
if val, exists := os.LookupEnv("faas_function_suffix"); exists {
|
||||
functionSuffix = val
|
||||
}
|
||||
|
||||
if val, exists := os.LookupEnv("faas_print_body"); exists {
|
||||
debugPrintBody = val == "1" || val == "true"
|
||||
}
|
||||
|
||||
var durable string
|
||||
var qgroup string
|
||||
var unsubscribe bool
|
||||
|
||||
client := makeClient()
|
||||
sc, err := stan.Connect(clusterID, clientID, stan.NatsURL("nats://"+natsAddress+":4222"))
|
||||
if err != nil {
|
||||
log.Fatalf("Can't connect: %v\n", err)
|
||||
}
|
||||
|
||||
startOpt := stan.StartWithLastReceived()
|
||||
|
||||
i := 0
|
||||
mcb := func(msg *stan.Msg) {
|
||||
i++
|
||||
|
||||
printMsg(msg, i)
|
||||
|
||||
started := time.Now()
|
||||
|
||||
req := queue.Request{}
|
||||
unmarshalErr := json.Unmarshal(msg.Data, &req)
|
||||
if unmarshalErr != nil {
|
||||
log.Printf("Unmarshal error: %s with data %s", unmarshalErr, msg.Data)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Request for %s.\n", req.Function)
|
||||
if debugPrintBody {
|
||||
fmt.Println(string(req.Body))
|
||||
}
|
||||
|
||||
queryString := ""
|
||||
if len(req.QueryString) > 0 {
|
||||
queryString = fmt.Sprintf("?%s", strings.TrimLeft(req.QueryString, "?"))
|
||||
}
|
||||
|
||||
functionURL := fmt.Sprintf("http://%s%s:8080/%s", req.Function, functionSuffix, queryString)
|
||||
|
||||
request, err := http.NewRequest("POST", functionURL, bytes.NewReader(req.Body))
|
||||
defer request.Body.Close()
|
||||
|
||||
for k, v := range req.Header {
|
||||
request.Header[k] = v
|
||||
}
|
||||
|
||||
res, err := client.Do(request)
|
||||
var status int
|
||||
var functionResult []byte
|
||||
|
||||
if err != nil {
|
||||
status = http.StatusServiceUnavailable
|
||||
|
||||
log.Println(err)
|
||||
timeTaken := time.Since(started).Seconds()
|
||||
|
||||
if req.CallbackURL != nil {
|
||||
log.Printf("Callback to: %s\n", req.CallbackURL.String())
|
||||
|
||||
resultStatusCode, resultErr := postResult(&client, req, functionResult, status)
|
||||
if resultErr != nil {
|
||||
log.Println(resultErr)
|
||||
} else {
|
||||
log.Printf("Posted result: %d", resultStatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
statusCode, reportErr := postReport(&client, req.Function, status, timeTaken, gatewayAddress)
|
||||
if reportErr != nil {
|
||||
log.Println(reportErr)
|
||||
} else {
|
||||
log.Printf("Posting report - %d\n", statusCode)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
|
||||
resData, err := ioutil.ReadAll(res.Body)
|
||||
functionResult = resData
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
fmt.Println(string(functionResult))
|
||||
}
|
||||
|
||||
timeTaken := time.Since(started).Seconds()
|
||||
|
||||
fmt.Println(res.Status)
|
||||
|
||||
if req.CallbackURL != nil {
|
||||
log.Printf("Callback to: %s\n", req.CallbackURL.String())
|
||||
resultStatusCode, resultErr := postResult(&client, req, functionResult, res.StatusCode)
|
||||
if resultErr != nil {
|
||||
log.Println(resultErr)
|
||||
} else {
|
||||
log.Printf("Posted result: %d", resultStatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
statusCode, reportErr := postReport(&client, req.Function, res.StatusCode, timeTaken, gatewayAddress)
|
||||
|
||||
if reportErr != nil {
|
||||
log.Println(reportErr)
|
||||
} else {
|
||||
log.Printf("Posting report - %d\n", statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
subj := "faas-request"
|
||||
qgroup = "faas"
|
||||
|
||||
ackWait := time.Second * 30
|
||||
maxInflight := 1
|
||||
|
||||
if value, exists := os.LookupEnv("max_inflight"); exists {
|
||||
val, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
log.Println("max_inflight error:", err)
|
||||
} else {
|
||||
maxInflight = val
|
||||
}
|
||||
}
|
||||
|
||||
if val, exists := os.LookupEnv("ack_wait"); exists {
|
||||
ackWaitVal, durationErr := time.ParseDuration(val)
|
||||
if durationErr != nil {
|
||||
log.Println("ack_wait error:", durationErr)
|
||||
} else {
|
||||
ackWait = ackWaitVal
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Wait for ", ackWait)
|
||||
sub, err := sc.QueueSubscribe(subj, qgroup, mcb, startOpt, stan.DurableName(durable), stan.MaxInflight(maxInflight), stan.AckWait(ackWait))
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
log.Printf("Listening on [%s], clientID=[%s], qgroup=[%s] durable=[%s]\n", subj, clientID, qgroup, durable)
|
||||
|
||||
// Wait for a SIGINT (perhaps triggered by user with CTRL-C)
|
||||
// Run cleanup when signal is received
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
cleanupDone := make(chan bool)
|
||||
signal.Notify(signalChan, os.Interrupt)
|
||||
go func() {
|
||||
for _ = range signalChan {
|
||||
fmt.Printf("\nReceived an interrupt, unsubscribing and closing connection...\n\n")
|
||||
// Do not unsubscribe a durable on exit, except if asked to.
|
||||
if durable == "" || unsubscribe {
|
||||
sub.Unsubscribe()
|
||||
}
|
||||
sc.Close()
|
||||
cleanupDone <- true
|
||||
}
|
||||
}()
|
||||
<-cleanupDone
|
||||
}
|
||||
|
||||
func postResult(client *http.Client, req queue.Request, result []byte, statusCode int) (int, error) {
|
||||
var reader io.Reader
|
||||
|
||||
if result != nil {
|
||||
reader = bytes.NewReader(result)
|
||||
}
|
||||
|
||||
request, err := http.NewRequest("POST", req.CallbackURL.String(), reader)
|
||||
res, err := client.Do(request)
|
||||
|
||||
if err != nil {
|
||||
return http.StatusBadGateway, fmt.Errorf("error posting result to URL %s %s", req.CallbackURL.String(), err.Error())
|
||||
}
|
||||
|
||||
if request.Body != nil {
|
||||
defer request.Body.Close()
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
return res.StatusCode, nil
|
||||
}
|
||||
|
||||
func postReport(client *http.Client, function string, statusCode int, timeTaken float64, gatewayAddress string) (int, error) {
|
||||
req := AsyncReport{
|
||||
FunctionName: function,
|
||||
StatusCode: statusCode,
|
||||
TimeTaken: timeTaken,
|
||||
}
|
||||
|
||||
targetPostback := "http://" + gatewayAddress + ":8080/system/async-report"
|
||||
reqBytes, _ := json.Marshal(req)
|
||||
request, err := http.NewRequest("POST", targetPostback, bytes.NewReader(reqBytes))
|
||||
defer request.Body.Close()
|
||||
|
||||
res, err := client.Do(request)
|
||||
|
||||
if err != nil {
|
||||
return http.StatusGatewayTimeout, fmt.Errorf("cannot post report to %s: %s", targetPostback, err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
return res.StatusCode, nil
|
||||
}
|
Reference in New Issue
Block a user