Merge branch 'master' of github.com:iron-io/functions into runner-route-not-found

This commit is contained in:
Pedro Nasser
2016-08-30 22:41:09 -03:00
15 changed files with 95 additions and 63 deletions

View File

@@ -23,12 +23,10 @@ curl -H "Content-Type: application/json" -X POST -d '{
}' http://localhost:8080/v1/apps }' http://localhost:8080/v1/apps
``` ```
Now that we have an app, we can add routes to functions. Now that we have an app, we can map routes to functions.
### Add a route to a Function ### Add a route to a Function
```sh ```sh
curl -H "Content-Type: application/json" -X POST -d '{ curl -H "Content-Type: application/json" -X POST -d '{
"route": { "route": {
@@ -70,6 +68,10 @@ And you'll get an ironfunctions.com host for your app:
myapp.USER_ID.ironfunctions.com/hello myapp.USER_ID.ironfunctions.com/hello
``` ```
## API Reference
https://swaggerhub.com/api/iron/functions
## Full Documentation ## Full Documentation
http://docs-new.iron.io/docs http://docs-new.iron.io/docs

37
api/runner/logger.go Normal file
View File

@@ -0,0 +1,37 @@
package runner
import (
"bufio"
"io"
"github.com/Sirupsen/logrus"
)
// FuncLogger reads STDERR output from a container and outputs it in a parseable structured log format, see: https://github.com/iron-io/functions/issues/76
type FuncLogger struct {
r io.Reader
w io.Writer
}
func NewFuncLogger(appName, path, function, requestID string) io.Writer {
r, w := io.Pipe()
funcLogger := &FuncLogger{
r: r,
w: w,
}
log := logrus.WithFields(logrus.Fields{"user_log": true, "app_name": appName, "path": path, "function": function, "request_id": requestID})
go func(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
log.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.WithError(err).Println("There was an error with the scanner in attached container")
}
}(r)
return funcLogger
}
func (l *FuncLogger) Write(p []byte) (n int, err error) {
return l.w.Write(p)
}

View File

@@ -56,5 +56,5 @@ func handleAppCreate(c *gin.Context) {
return return
} }
c.JSON(http.StatusCreated, appResponse{"App successfully created", wapp}) c.JSON(http.StatusCreated, appResponse{"App successfully created", wapp.App})
} }

View File

@@ -29,5 +29,5 @@ func handleAppGet(c *gin.Context) {
return return
} }
c.JSON(http.StatusOK, &models.AppWrapper{app}) c.JSON(http.StatusOK, appResponse{"Successfully loaded app", app})
} }

View File

@@ -23,5 +23,5 @@ func handleAppList(c *gin.Context) {
return return
} }
c.JSON(http.StatusOK, &models.AppsWrapper{apps}) c.JSON(http.StatusOK, appsResponse{"Successfully listed applications", apps})
} }

View File

@@ -39,5 +39,5 @@ func handleAppUpdate(c *gin.Context) {
wapp.App = app wapp.App = app
// Nothing to update right now in apps // Nothing to update right now in apps
c.JSON(http.StatusOK, appResponse{"App successfully updated", wapp}) c.JSON(http.StatusOK, appResponse{"App successfully updated", wapp.App})
} }

View File

@@ -17,23 +17,23 @@ import (
) )
type appResponse struct { type appResponse struct {
Message string Message string `json:"message"`
App models.AppWrapper App *models.App `json:"app"`
} }
type appsResponse struct { type appsResponse struct {
Message string Message string `json:"message"`
Apps models.AppsWrapper Apps models.Apps `json:"apps"`
} }
type routeResponse struct { type routeResponse struct {
Message string Message string `json:"message"`
Route models.RouteWrapper Route *models.Route `json:"route"`
} }
type routesResponse struct { type routesResponse struct {
Message string Message string `json:"message"`
Routes models.RoutesWrapper Routes models.Routes `json:"routes"`
} }
func testRouter() *gin.Engine { func testRouter() *gin.Engine {

View File

@@ -75,5 +75,5 @@ func handleRouteCreate(c *gin.Context) {
return return
} }
c.JSON(http.StatusCreated, routeResponse{"Route successfully created", wroute}) c.JSON(http.StatusCreated, routeResponse{"Route successfully created", wroute.Route})
} }

View File

@@ -33,5 +33,5 @@ func handleRouteGet(c *gin.Context) {
log.WithFields(logrus.Fields{"route": route}).Debug("Got route") log.WithFields(logrus.Fields{"route": route}).Debug("Got route")
c.JSON(http.StatusOK, &models.RouteWrapper{route}) c.JSON(http.StatusOK, routeResponse{"Successfully loaded route", route})
} }

View File

@@ -37,5 +37,5 @@ func handleRouteList(c *gin.Context) {
log.WithFields(logrus.Fields{"routes": routes}).Debug("Got routes") log.WithFields(logrus.Fields{"routes": routes}).Debug("Got routes")
c.JSON(http.StatusOK, &models.RoutesWrapper{Routes: routes}) c.JSON(http.StatusOK, routesResponse{"Sucessfully listed routes", routes})
} }

View File

@@ -45,5 +45,5 @@ func handleRouteUpdate(c *gin.Context) {
return return
} }
c.JSON(http.StatusOK, routeResponse{"Route successfully updated", wroute}) c.JSON(http.StatusOK, routeResponse{"Route successfully updated", wroute.Route})
} }

View File

@@ -106,7 +106,9 @@ func handleRunner(c *gin.Context) {
log.WithField("routes", routes).Debug("Got routes from datastore") log.WithField("routes", routes).Debug("Got routes from datastore")
for _, el := range routes { for _, el := range routes {
if params, match := matchRoute(el.Path, route); match { if params, match := matchRoute(el.Path, route); match {
var stdout, stderr bytes.Buffer
var stdout bytes.Buffer // TODO: should limit the size of this, error if gets too big. akin to: https://golang.org/pkg/io/#LimitReader
stderr := runner.NewFuncLogger(appName, route, el.Image, reqID)
envVars := map[string]string{ envVars := map[string]string{
"METHOD": c.Request.Method, "METHOD": c.Request.Method,
@@ -130,13 +132,18 @@ func handleRunner(c *gin.Context) {
envVars["PARAM_"+strings.ToUpper(param.Key)] = param.Value envVars["PARAM_"+strings.ToUpper(param.Key)] = param.Value
} }
// headers
for header, value := range c.Request.Header {
envVars["HEADER_"+strings.ToUpper(header)] = strings.Join(value, " ")
}
cfg := &runner.Config{ cfg := &runner.Config{
Image: el.Image, Image: el.Image,
Timeout: 30 * time.Second, Timeout: 30 * time.Second,
ID: reqID, ID: reqID,
AppName: appName, AppName: appName,
Stdout: &stdout, Stdout: &stdout,
Stderr: &stderr, Stderr: stderr,
Env: envVars, Env: envVars,
} }
@@ -151,7 +158,7 @@ func handleRunner(c *gin.Context) {
if result.Status() == "success" { if result.Status() == "success" {
c.Data(http.StatusOK, "", stdout.Bytes()) c.Data(http.StatusOK, "", stdout.Bytes())
} else { } else {
log.WithFields(logrus.Fields{"app": appName, "route": el, "req_id": reqID}).Debug(stderr.String()) // log.WithFields(logrus.Fields{"app": appName, "route": el, "req_id": reqID}).Debug(stderr.String())
c.AbortWithStatus(http.StatusInternalServerError) c.AbortWithStatus(http.StatusInternalServerError)
} }
} }

View File

@@ -7,7 +7,7 @@ import (
) )
// Version of IronFunctions // Version of IronFunctions
var Version = "0.0.2" var Version = "0.0.32"
func handleVersion(c *gin.Context) { func handleVersion(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"version": Version}) c.JSON(http.StatusOK, gin.H{"version": Version})

View File

@@ -6,7 +6,7 @@ name = "World"
# or using env vars: ENV['PAYLOAD'] # or using env vars: ENV['PAYLOAD']
payload = ENV['PAYLOAD'] payload = ENV['PAYLOAD']
puts 'ARGF: ' + payload.inspect STDERR.puts 'payload: ' + payload.inspect
if payload != "" if payload != ""
payload = JSON.parse(payload) payload = JSON.parse(payload)
name = payload['name'] name = payload['name']

64
glide.lock generated
View File

@@ -1,5 +1,5 @@
hash: 5ccf89905e13b7dc987cd203c1d7c1fddd32dcd776fe2e5f60d9f6f7b9908425 hash: 5ccf89905e13b7dc987cd203c1d7c1fddd32dcd776fe2e5f60d9f6f7b9908425
updated: 2016-08-24T14:50:27.724858484-03:00 updated: 2016-08-30T10:32:52.850687756-07:00
imports: imports:
- name: github.com/amir/raidman - name: github.com/amir/raidman
version: c74861fe6a7bb8ede0a010ce4485bdbb4fc4c985 version: c74861fe6a7bb8ede0a010ce4485bdbb4fc4c985
@@ -13,10 +13,6 @@ imports:
version: 1c27c506c7a0584d017ca479f91b88d6a6538332 version: 1c27c506c7a0584d017ca479f91b88d6a6538332
subpackages: subpackages:
- statsd - statsd
- name: github.com/dgrijalva/jwt-go
version: 63734eae1ef55eaac06fdc0f312615f2e321e273
subpackages:
- request
- name: github.com/docker/distribution - name: github.com/docker/distribution
version: 9ca7921603852314b18a6ecc19f91806935f34bd version: 9ca7921603852314b18a6ecc19f91806935f34bd
subpackages: subpackages:
@@ -29,23 +25,22 @@ imports:
- pkg/archive - pkg/archive
- pkg/fileutils - pkg/fileutils
- pkg/homedir - pkg/homedir
- pkg/stdcopy
- pkg/idtools
- pkg/ioutils - pkg/ioutils
- pkg/parsers
- pkg/pools - pkg/pools
- pkg/promise - pkg/promise
- pkg/system
- pkg/longpath
- pkg/random - pkg/random
- pkg/units - pkg/stdcopy
- pkg/system
- pkg/tarsum - pkg/tarsum
- pkg/ulimit
- pkg/units
- volume
- name: github.com/docker/engine-api - name: github.com/docker/engine-api
version: 2f8c367944a28130f3c2fb9f0aad7f1d5db952a9 version: 2f8c367944a28130f3c2fb9f0aad7f1d5db952a9
subpackages: subpackages:
- types/swarm
- types/filters
- types/mount - types/mount
- types/versions - types/swarm
- name: github.com/docker/go-units - name: github.com/docker/go-units
version: eb879ae3e2b84e2a142af415b679ddeda47ec71c version: eb879ae3e2b84e2a142af415b679ddeda47ec71c
- name: github.com/docker/libtrust - name: github.com/docker/libtrust
@@ -57,8 +52,8 @@ imports:
- name: github.com/garyburd/redigo - name: github.com/garyburd/redigo
version: 4ed1111375cbeb698249ffe48dd463e9b0a63a7a version: 4ed1111375cbeb698249ffe48dd463e9b0a63a7a
subpackages: subpackages:
- redis
- internal - internal
- redis
- name: github.com/gin-gonic/gin - name: github.com/gin-gonic/gin
version: 4a6bc4aac4607e253bcda67c8c5bcda693d2388e version: 4a6bc4aac4607e253bcda67c8c5bcda693d2388e
subpackages: subpackages:
@@ -97,10 +92,10 @@ imports:
subpackages: subpackages:
- hcl/ast - hcl/ast
- hcl/parser - hcl/parser
- hcl/token
- json/parser
- hcl/scanner - hcl/scanner
- hcl/strconv - hcl/strconv
- hcl/token
- json/parser
- json/scanner - json/scanner
- json/token - json/token
- name: github.com/heroku/docker-registry-client - name: github.com/heroku/docker-registry-client
@@ -108,21 +103,21 @@ imports:
subpackages: subpackages:
- registry - registry
- name: github.com/iron-io/titan - name: github.com/iron-io/titan
version: 58d1565025aa045bdf47b44e0eb81a52c70f7958 version: 3bb6aacb244a24e38bba755cc863533810117a5c
repo: https://github.com/iron-io/titan.git repo: https://github.com/iron-io/titan.git
vcs: git vcs: git
subpackages: subpackages:
- common - common
- common/stats
- runner/agent - runner/agent
- runner/drivers - runner/drivers
- runner/drivers/docker - runner/drivers/docker
- runner/drivers/mock - runner/drivers/mock
- runner/tasker - runner/tasker
- common/stats
- runner/tasker/client/models - runner/tasker/client/models
- runner/tasker/client/titan - runner/tasker/client/titan
- runner/tasker/client/titan/jobs
- runner/tasker/client/titan/groups - runner/tasker/client/titan/groups
- runner/tasker/client/titan/jobs
- runner/tasker/client/titan/runner - runner/tasker/client/titan/runner
- name: github.com/kr/fs - name: github.com/kr/fs
version: 2788f0dbd16903de03cb8186e5c7d97b69ad387b version: 2788f0dbd16903de03cb8186e5c7d97b69ad387b
@@ -135,9 +130,9 @@ imports:
- name: github.com/mailru/easyjson - name: github.com/mailru/easyjson
version: 34560e358dc05e2c28f6fda2f5c9e7494a4b9b19 version: 34560e358dc05e2c28f6fda2f5c9e7494a4b9b19
subpackages: subpackages:
- buffer
- jlexer - jlexer
- jwriter - jwriter
- buffer
- name: github.com/manucorporat/sse - name: github.com/manucorporat/sse
version: ee05b128a739a0fb76c7ebd3ae4810c1de808d6d version: ee05b128a739a0fb76c7ebd3ae4810c1de808d6d
- name: github.com/mitchellh/mapstructure - name: github.com/mitchellh/mapstructure
@@ -145,7 +140,6 @@ imports:
- name: github.com/opencontainers/runc - name: github.com/opencontainers/runc
version: 46d9535096662d8d6a734e4fdfc1c27ab03bc328 version: 46d9535096662d8d6a734e4fdfc1c27ab03bc328
subpackages: subpackages:
- libcontainer/system
- libcontainer/user - libcontainer/user
- name: github.com/pelletier/go-buffruneio - name: github.com/pelletier/go-buffruneio
version: df1e16fde7fc330a0ca68167c23bf7ed6ac31d6d version: df1e16fde7fc330a0ca68167c23bf7ed6ac31d6d
@@ -181,20 +175,19 @@ imports:
- name: github.com/spf13/viper - name: github.com/spf13/viper
version: 7fb2782df3d83e0036cc89f461ed0422628776f4 version: 7fb2782df3d83e0036cc89f461ed0422628776f4
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: c10c31b5e94b6f7a0283272dc2bb27163dcea24b version: b13fc1fd382d01861b16b2e6474487d3d4d27f20
subpackages: subpackages:
- bcrypt
- blowfish
- ssh
- curve25519 - curve25519
- ed25519 - ed25519
- ed25519/internal/edwards25519
- ssh
- name: golang.org/x/net - name: golang.org/x/net
version: f315505cf3349909cdf013ea56690da34e96a451 version: f315505cf3349909cdf013ea56690da34e96a451
subpackages: subpackages:
- context - context
- context/ctxhttp - context/ctxhttp
- proxy
- idna - idna
- proxy
- name: golang.org/x/sys - name: golang.org/x/sys
version: a646d33e2ee3172a661fc09bca23bb4889a41bc8 version: a646d33e2ee3172a661fc09bca23bb4889a41bc8
subpackages: subpackages:
@@ -202,25 +195,18 @@ imports:
- name: golang.org/x/text - name: golang.org/x/text
version: d69c40b4be55797923cec7457fac7a244d91a9b6 version: d69c40b4be55797923cec7457fac7a244d91a9b6
subpackages: subpackages:
- transform
- unicode/norm
- secure/precis
- cases - cases
- internal/tag
- language
- runes - runes
- secure/bidirule - secure/bidirule
- width - secure/precis
- language - transform
- unicode/bidi - unicode/bidi
- internal/tag - unicode/norm
- width
- name: gopkg.in/go-playground/validator.v8 - name: gopkg.in/go-playground/validator.v8
version: c193cecd124b5cc722d7ee5538e945bdb3348435 version: c193cecd124b5cc722d7ee5538e945bdb3348435
- name: gopkg.in/mgo.v2
version: 3f83fa5005286a7fe593b055f0d7771a7dce4655
subpackages:
- bson
- internal/sasl
- internal/scram
- internal/json
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: e4d366fc3c7938e2958e662b4258c7a89e1f0e3e version: e4d366fc3c7938e2958e662b4258c7a89e1f0e3e
testImports: [] testImports: []