update docs and contributing

This commit is contained in:
Pedro Nasser
2016-07-27 17:51:51 -03:00
parent f09a4cc94f
commit 338498e94d
14 changed files with 194 additions and 350 deletions

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@ vendor/
/gateway /gateway
/functions /functions
bolt.db bolt.db
.glide/
private.sh private.sh
.env .env

View File

@@ -1,23 +1,24 @@
## Building
## Building/Testing First time or when a dependency changes or when the API changes, run:
```
Build:
```sh
# one time:
glide install glide install
# then every time
./build.sh
``` ```
Test it, the iron token and project id are for cache. To quick build and run (using default database):
```sh ```sh
docker run --env-file .env --rm -it --privileged -p 8080:8080 iron/functions hack/api.sh
```
To build the docker image:
```sh
hack/build.sh
``` ```
## Releasing ## Releasing
```sh ```sh
./release.sh hack/release.sh
``` ```

106
README.md
View File

@@ -1,54 +1,80 @@
Note: currently running at: http://gateway.iron.computer:8080/
# IronFunctions # IronFunctions
First, let's fire up an IronFunctions instance. Copy the [example.env](example.env) file into a file named `.env` and fill in the missing values. ## [Overview](/iron-io/functions/blob/master/OVERVIEW.md)
Then start your functions instance: ## Quick Start
First let's start our IronFunctions API
``` ```
docker run --env-file .env --rm -it --privileged -p 8080:8080 iron/functions docker run --rm -it -p 8080:8080 iron/functions
``` ```
## Usage This command will quickly start our API using the default database `Bolt` running on `:8080`
First things first, create an app/service: Now that we have our API up and running we can quickly create our first function
TOOD: App or service??
### Create App ```
curl -H "Content-Type: application/json" -X POST -d '{
"name": "MyRoute"
"path": "/myroute"
"image": "iron/hello"
}' http://localhost:8080/v1/apps/myapp/routes
```
Done. Now you have our first IronFunctions route ready.
Now let's test our new route.
```
curl http://localhost:8080/r/myapp/myroute
```
## Configuring your API
### Databases
These are the current databases supported by IronFunctions:
- [Running with BoltDB](/iron-io/functions/blob/master/docs/database/boltdb.md)
- [Running with Postgres](/iron-io/functions/blob/master/docs/database/postgres.md)
## API Usage
### Creating applications
```sh ```sh
iron create app APP_NAME curl -H "Content-Type: application/json" -X POST -d '{
# OR "name":"APP_NAME"
curl -H "Content-Type: application/json" -X POST -d '{"name":"APP_NAME"}' http://localhost:8080/api/v1/apps }' http://localhost:8080/v1/apps
``` ```
### Create a Route for your Function ### Creating routes in a application
Now add routes to the app. First we'll add a route to the output of a docker container: Now add routes to the app. First we'll add a route to the output of a docker container:
```sh ```sh
iron add route myapp /hello iron/hello curl -H "Content-Type: application/json" -X POST -d '{
# OR "name": "hello",
curl -H "Content-Type: application/json" -X POST -d '{"path":"/hello", "image":"iron/hello"}' http://localhost:8080/api/v1/apps/myapp/routes "path":"/hello",
``` "image":"iron/hello"
}' http://localhost:8080/v1/apps/myapp/routes
And how about a [slackbot](https://github.com/treeder/slackbots/tree/master/guppy) too:
```sh
curl -H "Content-Type: application/json" -X POST -d '{"path":"/guppy","image":"treeder/guppy:0.0.2", "content_type": "application/json"}' http://localhost:8080/api/v1/apps/myapp/routes
``` ```
### Calling your Function ### Calling your Function
Surf to your function: http://localhost:8080/hello?app=APP_NAME . Boom! ```
curl http://localhost:8080/r/myapp/hello
```
#### To pass in data to your function, ### To pass in data to your function,
Your function will get the body of the request as is, and the headers of the request will be passed in as env vars. Your function will get the body of the request as is, and the headers of the request will be passed in as env vars.
```sh ```sh
curl -H "Content-Type: application/json" -X POST -d '{"name":"Johnny"}' http://localhost:8080/hello?app=APP_NAME curl -H "Content-Type: application/json" -X POST -d '{
"name":"Johnny"
}' http://localhost:8080/r/myapp/hello
``` ```
### Using IronFunctions Hosted by Iron.io ### Using IronFunctions Hosted by Iron.io
@@ -56,38 +82,26 @@ curl -H "Content-Type: application/json" -X POST -d '{"name":"Johnny"}' http://l
Simply point to https://functions.iron.io instead of localhost and add your Iron.io Authentication header (TODO: link), like this: Simply point to https://functions.iron.io instead of localhost and add your Iron.io Authentication header (TODO: link), like this:
```sh ```sh
curl -H "Authorization: Bearer IRON_TOKEN" -H "Content-Type: application/json" -X POST -d '{"name":"APP_NAME"}' https://functions.iron.io/api/v1/apps curl -H "Authorization: Bearer IRON_TOKEN" -H "Content-Type: application/json" -X POST -d '{"name":"APP_NAME"}' https://functions.iron.io/v1/apps
``` ```
And you'll get an ironfunctions.com host: And you'll get an ironfunctions.com host:
``` ```
APP_NAME.ironfunctions.com/PATH APP_NAME.USER_ID.ironfunctions.com/PATH
``` ```
### Updating Your Images ## [Examples](/iron-io/functions/blob/master/examples)
Tag your images with a version, eg `treeder/guppy:0.0.5` then use that including the tag and update ## Logging
the route.
## Examples
TODO: Link to examples in various languages
TODO: Link to slackbots (easiest way to host slackbots?)
## Operations
This is info on how to run and manage IronFunctions.
### Logging
Run logspout container on your server.
#### Monitoring
TODO TODO
### Scaling ## Monitoring
TODO
## Scaling
TODO TODO

0
docs/api.md Normal file
View File

11
docs/database/boltdb.md Normal file
View File

@@ -0,0 +1,11 @@
# IronFunctions using BoltDB
BoltDB is the default database, you just need to run the API.
## Persistent
To keep it persistent you add a volume flag to the command:
```
docker run --rm -it -v $PWD/bold.db:/app/bolt.db -p 8080:8080 iron/functions
```

34
docs/database/postgres.md Normal file
View File

@@ -0,0 +1,34 @@
# IronFunctions using Postgres
Let's presuppose you don't have even a postgres DB ready.
### 1. Let's start a postgres instance:
```
docker run --name iron-postgres \
-e POSTGRES_PASSWORD=ironfunctions -d postgres
```
### 2. Now let's create a new database to IronFunctions
Creating database:
```
docker run -it --rm --link iron-postgres:postgres postgres \
psql -h postgres -U postgres -c "CREATE DATABASE funcs;"
```
Granting access to postgres user
```
docker run -it --rm --link iron-postgres:postgres postgres \
psql -h postgres -U postgres -c 'GRANT ALL PRIVILEGES ON DATABASE funcs TO postgres;'
```
### 3. Now let's start IronFunctions connecting to our new postgres instance
```
docker run --rm --link "iron-postgres:postgres" \
-e "DB=postgres://postgres:ironfunctions@postgres/funcs?sslmode=disable" \
-it -p 8080:8080 iron/functions
```

View File

@@ -1,9 +0,0 @@
# For IronCache
IRON_TOKEN=X
IRON_PROJECT_ID=X
# For CloudFlare dns support
CLOUDFLARE_EMAIL=you@example.com
CLOUDFLARE_API_KEY=X
# See comments here to get zone id https://blog.cloudflare.com/cloudflare-tips-frequently-used-cloudflare-ap/#comment-2412200222
CLOUDFLARE_ZONE_ID=y

View File

@@ -1,23 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAhof/Rgb5YUGUCynxYAkbkSRQqIaaZem7g6r/lyePBk6IKzjia6QA+Ut+1KZt
uGrNXFR0THtfEWCFjIPBJfYLGmkG1gaYocWJUu/b3be3rKGlLWEuSpfHsYyLh4803QNU79Uu0ft8
ODB4QJl54WImD1JKzAZyarDalyb+GKbnU5NAULBbTccbGFbNSwPwebvoK9G6Z8qWChPqsYAZxfyC
D2LBt0PANwB+haC6Rj0t99R6mtLRz/iKYaHz26d6UxSzNsXArJlhSCABHdQ71rbPkO0M9PvJrhfg
y+bLA4sMrHvOSjEDWGY+j1qqEYXSc/Rwe5SMd8kV7i902ks7PjcCZQIDAQABAoIBAHjvlHk9F71o
GE+Y2tV8Gn31aVS1++IVpW2NsMoO07HVsu836cLd4co5JcDAA+4+hHG1sf53AVU7sZJJdr5LWlvZ
gj2wHFGApBwcZ0f/OWxEu5n5vIVtwCRJtbyc7eaochhPShGVw2s3l0JrNXd4pcIsNfUG7qAeb8Jl
WRKMJ3OmoEMOz5M3scRypQKOulRjO6RMJCtbl4AntMYNF7cdWeuIJ3eaMD8HaYbkr1USrwGk65QC
mKdUcNl9k++Txuf7UtbRB0apFsMnAKRPUTU+9TPGwMsZSzszk8TClMNO1ALYKKY5mE+cPqrAl5gC
ZpPOf45oT+2lxktqq5u5N8XMFoECgYEA16eGE3inh23EVly5ARnowGgFtorZsI6XIJHkYsETRocf
GAvQrEMAuFWZy0n5TlNBfzPhHh9rUXWCKlbldgnDgWKpphPux3UXTqTUak+j6397rtEP85RfYqDm
QxtW0uOkKkZSGyXXEYBwTbCsQBH28VZsJEYVe+G3uXPcUu3WEZUCgYEAn7Mwgk/JP5wgYo4E3gga
fOi0/de11MV5ad337qfdUC1pf1ju9q2CyHaV3g6eo2OnynGZHYq5qlyLWoi/hTr6A+yMZSnQ15io
9ker4uyAX6DdVDmWK9uErwrqLAV+Q6HoVmxoyBbMihQW8TqX/5jZegxqipDW16+qOFxtPbZhmZEC
gYEAlD85UBFVOSggHC5Jj5Q8CGh55O62j0S2Z1Fjau/HTGh+24zjukelKxLNUo5br5hUIhmL26VF
pQ3emTR7MRWtLDii3uQ89ShtCUcOLrbovG86mwZkrNGGcMqi/+a/XOHYbKdCsh7lJcbhbMbS4oh2
9ZivZpA3HJ4iKn6XKvsMebECgYEAhNWXU8zpqG9EwLVAdy5mWd92LG5wYDqhct2ejHQ0MayUQ8jF
e4l3bya0IbAnY+BQgKNcqKXrKTkw8G0uYLNdokXvwXW2sJ3abH/RCT+Ox/wWHSiJMJG3G6IIhfVL
wRW7G6ewwD22hGORcbU7GO8addo+BGPVUDJdc+PtOZeqNwECgYEAvLJQas3PKLL+qVmO9asvDtCl
tvOuvPFAuZBk6hLm9SSrFt5cCW+rulL8Kx1PxUk0C8LiJV8uwZIqQxE+gY5MkCfvt+xG1yurkywd
SCHOFr0m4gi8+XHvL4fmGzYPgHRi10kepSta5G8USigbcf5fOmw+Upa3qVnwot3CQdxmSfU=
-----END RSA PRIVATE KEY-----

118
glide.lock generated
View File

@@ -1,75 +1,71 @@
hash: a104a522dc2ba982d25101330bbd5d44778565128f0cb09f34061c167921046c hash: 2101b4c83f12c75cbc3cb5be0a7d544dd3a7d21a27ef8a5ee8b014ded8cee034
updated: 2016-07-14T08:40:37.798125603-07:00 updated: 2016-07-27T16:56:51.792310167-03:00
imports: imports:
- name: github.com/amir/raidman - name: github.com/asaskevich/govalidator
version: 91c20f3f475cab75bb40ad7951d9bbdde357ade7 version: 593d64559f7600f29581a3ee42177f5dbded27a9
- name: github.com/boltdb/bolt
version: 5cc10bbbc5c141029940133bb33c9e969512a698
- name: github.com/gin-gonic/gin
version: 4a6bc4aac4607e253bcda67c8c5bcda693d2388e
subpackages: subpackages:
- proto - binding
- name: github.com/BurntSushi/toml - render
version: bec2dacf4b590d26237cfebff4471e21ce543494 - name: github.com/go-openapi/analysis
- name: github.com/cactus/go-statsd-client version: abc9a6171f5bf03ada39aead1aa7fd7bbd44d50f
version: 91c326c3f7bd20f0226d3d1c289dd9f8ce28d33d - name: github.com/go-openapi/errors
subpackages: version: d24ebc2075bad502fac3a8ae27aa6dd58e1952dc
- statsd - name: github.com/go-openapi/jsonpointer
- name: github.com/dgrijalva/jwt-go version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
version: 01aeca54ebda6e0fbfafd0a524d234159c05ec20 - name: github.com/go-openapi/jsonreference
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
- name: github.com/go-openapi/loads
version: 18441dfa706d924a39a030ee2c3b1d8d81917b38
- name: github.com/go-openapi/runtime
version: 11e322eeecc1032d5a0a96c566ed53f2b5c26e22
- name: github.com/go-openapi/spec
version: e9fab754f5629065e6b7a6100301226545d4477e
- name: github.com/go-openapi/strfmt
version: dfda818c47a4ae5a1dde75ac776f34b2c95de993
- name: github.com/go-openapi/swag
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
- name: github.com/go-openapi/validate
version: deaf2c9013bc1a7f4c774662259a506ba874d80f
- name: github.com/golang/protobuf - name: github.com/golang/protobuf
version: 874264fbbb43f4d91e999fecb4b40143ed611400 version: 2402d76f3d41f928c7902a765dfc872356dd3aad
subpackages: subpackages:
- proto - proto
- name: github.com/gorilla/context - name: github.com/iron-io/titan
version: aed02d124ae4a0e94fea4541c8effd05bf0c8296 version: 697a5466b096fee73202f5ddccf8213a2357e062
- name: github.com/gorilla/mux repo: git@github.com:iron-io/titan.git
version: 9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e vcs: git
- name: github.com/iron-io/common
version: 7c9faec363c808052742b4c4b84876c4c2172308
subpackages: subpackages:
- httpshutdown - jobserver/models
- msgpack - name: github.com/lib/pq
- semaphore version: 3cd0097429be7d611bb644ef85b42bfb102ceea4
- serverutil
- name: github.com/iron-io/go
version: 1ed3de151aa27db91d6df5dc8c8ce164c833b57c
subpackages: subpackages:
- common - oid
- common/httpshutdown - name: github.com/mailru/easyjson
- common/msgpack version: 97eee20abef76a0591155412cf0d04f24b05098f
- common/semaphore
- common/stats
- name: github.com/iron-io/golog
version: 5b80d97af5a2a5d386e7609efb82192ae99a7c67
- name: github.com/iron-io/iron_go
version: 920c950272e820d9e2562fcbf40303f05564f118
subpackages: subpackages:
- cache - jlexer
- worker - jwriter
- api - buffer
- config - name: github.com/manucorporat/sse
- name: github.com/mattn/go-colorable version: ee05b128a739a0fb76c7ebd3ae4810c1de808d6d
version: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59 - name: github.com/PuerkitoBio/purell
- name: github.com/mattn/go-isatty version: 1d5d1cfad45d42ec5f81fa8ef23de09cebc6dcc3
version: 56b76bdf51f7708750eac80fa38b952bb9f32639 - name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/Sirupsen/logrus - name: github.com/Sirupsen/logrus
version: 32055c351ea8b00b96d70f28db48d9840feaf0ec version: a283a10442df8dc09befd873fab202bf8a253d6a
- name: github.com/vmihailenco/bufio
version: 24e7e48f60fc2d9e99e43c07485d9fff42051e66
- name: github.com/vrischmann/envconfig
version: 9e6e1c4d3b73427d03118518603bb904d9c55236
- name: golang.org/x/net - name: golang.org/x/net
version: a728288923b47049b2ce791836767ffbe964a5bd version: f315505cf3349909cdf013ea56690da34e96a451
subpackages: subpackages:
- proxy - context
- name: golang.org/x/sys - name: golang.org/x/sys
version: b518c298ac9dc94b6ac0757394f50d10c5dfa25a version: a646d33e2ee3172a661fc09bca23bb4889a41bc8
subpackages: subpackages:
- unix - unix
- name: gopkg.in/inconshreveable/log15.v2 - name: gopkg.in/go-playground/validator.v8
version: b105bd37f74e5d9dc7b6ad7806715c7a2b83fd3f version: c193cecd124b5cc722d7ee5538e945bdb3348435
subpackages: testImports: []
- stack
- term
- name: gopkg.in/mgo.v2
version: 29cc868a5ca65f401ff318143f9408d02f4799cc
subpackages:
- bson
devImports: []

View File

@@ -1,9 +1,14 @@
package: github.com/iron-io/microgateway package: github.com/iron-io/functions
import: import:
- package: github.com/gorilla/mux - package: github.com/Sirupsen/logrus
- package: github.com/iron-io/common - package: github.com/boltdb/bolt
- package: github.com/iron-io/golog - package: github.com/gin-gonic/gin
- package: github.com/iron-io/iron_go - package: github.com/go-openapi/errors
- package: github.com/go-openapi/strfmt
- package: github.com/go-openapi/validate
- package: github.com/iron-io/titan
repo: git@github.com:iron-io/titan.git
vcs: git
subpackages: subpackages:
- cache - jobserver/models
- worker - package: github.com/lib/pq

5
hack/api.sh Executable file
View File

@@ -0,0 +1,5 @@
set -ex
docker run --rm -v "$PWD":/go/src/github.com/iron-io/functions -w /go/src/github.com/iron-io/functions iron/go:dev sh -c 'go build -o functions'
docker build -t iron/functions:latest .
docker run --rm -it -p 8080:8080 -e LOG_LEVEL=debug -v $PWD/bolt.db:/app/bolt.db iron/functions

View File

@@ -15,7 +15,8 @@ perl -i -pe 's/\d+\.\d+\.\K(\d+)/$1+1/e' $version_file
version=$(grep -m1 -Eo "[0-9]+\.[0-9]+\.[0-9]+" $version_file) version=$(grep -m1 -Eo "[0-9]+\.[0-9]+\.[0-9]+" $version_file)
echo "Version: $version" echo "Version: $version"
./build.sh docker run --rm -v "$PWD":/go/src/github.com/iron-io/functions -w /go/src/github.com/iron-io/functions iron/go:dev sh -c 'go build -o functions'
docker build -t iron/functions:latest .
git add -u git add -u
git commit -m "$service: $version release" git commit -m "$service: $version release"

View File

@@ -1,192 +0,0 @@
/* I wanted to do some stuff to this so had to make a copy. Namely:
- change the Host handling for virtual hosts.
- get errors if the proxy request fails
*/
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// HTTP reverse proxy handler
package main
import (
"io"
"log"
"net"
"net/http"
"net/url"
"strings"
"sync"
"time"
)
// onExitFlushLoop is a callback set by tests to detect the state of the
// flushLoop() goroutine.
var onExitFlushLoop func()
// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
type ReverseProxy struct {
// Director must be a function which modifies
// the request into a new request to be sent
// using Transport. Its response is then copied
// back to the original client unmodified.
Director func(*http.Request)
// The transport used to perform proxy requests.
// If nil, http.DefaultTransport is used.
Transport http.RoundTripper
// FlushInterval specifies the flush interval
// to flush to the client while copying the
// response body.
// If zero, no periodic flushing is done.
FlushInterval time.Duration
}
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
switch {
case aslash && bslash:
return a + b[1:]
case !aslash && !bslash:
return a + "/" + b
}
return a + b
}
// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
targetQuery := target.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
}
return &ReverseProxy{Director: director}
}
func copyHeader(dst, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) error {
transport := p.Transport
if transport == nil {
transport = http.DefaultTransport
}
outreq := new(http.Request)
*outreq = *req // includes shallow copies of maps, but okay
p.Director(outreq)
outreq.Proto = "HTTP/1.1"
outreq.ProtoMajor = 1
outreq.ProtoMinor = 1
outreq.Close = false
// Remove the connection header to the backend. We want a
// persistent connection, regardless of what the client sent
// to us. This is modifying the same underlying map from req
// (shallow copied above) so we only copy it if necessary.
if outreq.Header.Get("Connection") != "" {
outreq.Header = make(http.Header)
copyHeader(outreq.Header, req.Header)
outreq.Header.Del("Connection")
}
if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
outreq.Header.Set("X-Forwarded-For", clientIp)
}
res, err := transport.RoundTrip(outreq)
if err != nil {
log.Printf("http: proxy error: %v", err)
// rw.WriteHeader(http.StatusInternalServerError)
return err
}
defer res.Body.Close()
copyHeader(rw.Header(), res.Header)
rw.WriteHeader(res.StatusCode)
p.copyResponse(rw, res.Body)
return nil
}
func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
if p.FlushInterval != 0 {
if wf, ok := dst.(writeFlusher); ok {
mlw := &maxLatencyWriter{
dst: wf,
latency: p.FlushInterval,
done: make(chan bool),
}
go mlw.flushLoop()
defer mlw.stop()
dst = mlw
}
}
io.Copy(dst, src)
}
type writeFlusher interface {
io.Writer
http.Flusher
}
type maxLatencyWriter struct {
dst writeFlusher
latency time.Duration
lk sync.Mutex // protects Write + Flush
done chan bool
}
func (m *maxLatencyWriter) Write(p []byte) (int, error) {
m.lk.Lock()
defer m.lk.Unlock()
return m.dst.Write(p)
}
func (m *maxLatencyWriter) flushLoop() {
t := time.NewTicker(m.latency)
defer t.Stop()
for {
select {
case <-m.done:
if onExitFlushLoop != nil {
onExitFlushLoop()
}
return
case <-t.C:
m.lk.Lock()
m.dst.Flush()
m.lk.Unlock()
}
}
panic("unreached")
}
func (m *maxLatencyWriter) stop() { m.done <- true }