mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Many updates, working ok at this point.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@ app.zip
|
|||||||
vendor/
|
vendor/
|
||||||
/microgateway
|
/microgateway
|
||||||
/gateway
|
/gateway
|
||||||
|
|
||||||
|
private.sh
|
||||||
|
|||||||
41
README.md
41
README.md
@@ -1,31 +1,39 @@
|
|||||||
|
Note: currently running at: http://gateway.iron.computer:8080/
|
||||||
|
|
||||||
# MicroServices Gateway / API Gateway
|
# MicroServices Gateway / API Gateway
|
||||||
|
|
||||||
First things first, register an app:
|
First things first, create an app/service:
|
||||||
|
|
||||||
|
TOOD: App or service??
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -H "Content-Type: application/json" -X POST -d '{"name":"myapp","password":"xyz"}' http://localhost:8080/test/1/projects/123/apps
|
iron create app
|
||||||
|
# OR
|
||||||
|
curl -H "Content-Type: application/json" -X POST -d '{"name":"myapp"}' http://localhost:8080/api/v1/apps
|
||||||
```
|
```
|
||||||
|
|
||||||
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
|
||||||
curl -H "Content-Type: application/json" -X POST -d '{"path":"/hello.rb","image":"treeder/hello.rb", "type":"run"}' http://localhost:8080/test/1/projects/123/apps/myapp/routes
|
iron add route myapp /hello iron/hello:0.0.1
|
||||||
|
# OR
|
||||||
|
curl -H "Content-Type: application/json" -X POST -d '{"path":"/hello", "image":"iron/hello", "type":"run"}' http://localhost:8080/api/v1/apps/myapp/routes
|
||||||
```
|
```
|
||||||
|
|
||||||
curl -H "Content-Type: application/json" -X POST -d '{"path":"/helloiron","image":"iron/hello", "type":"run"}' http://localhost:8080/test/1/projects/123/apps/myapp/routes
|
And how about a [slackbot](https://github.com/treeder/slackbots/tree/master/guppy) endpoint:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -H "Content-Type: application/json" -X POST -d '{"path":"/guppy","image":"treeder/guppy:0.0.2"}' http://localhost:8080/api/v1/apps/myapp/routes
|
||||||
|
```
|
||||||
|
|
||||||
Test out the route:
|
Test out the route:
|
||||||
|
|
||||||
```sh
|
Surf to: http://localhost:8080/hello?app=myapp
|
||||||
curl -i -X GET http://localhost:8080/hello.rb?app=myapp
|
|
||||||
```
|
|
||||||
|
|
||||||
Now try mapping an app endpoint:
|
Now try mapping an app endpoint:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -H "Content-Type: application/json" -X POST -d '{"path":"/sinatra","image":"treeder/hello-sinatra", "type":"app", "cpath":"/"}' http://localhost:8080/test/1/projects/123/apps/myapp/routes
|
curl -H "Content-Type: application/json" -X POST -d '{"path":"/sinatra","image":"treeder/hello-sinatra", "type":"app", "cpath":"/"}' http://localhost:8080/api/v1/apps/myapp/routes
|
||||||
```
|
```
|
||||||
|
|
||||||
And test it out:
|
And test it out:
|
||||||
@@ -37,7 +45,7 @@ curl -i -X GET http://localhost:8080/sinatra?app=myapp
|
|||||||
And another:
|
And another:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -H "Content-Type: application/json" -X POST -d '{"path":"/sinatra/ping","image":"treeder/hello-sinatra", "type":"app", "cpath":"/ping"}' http://localhost:8080/test/1/projects/123/apps/myapp/routes
|
curl -H "Content-Type: application/json" -X POST -d '{"path":"/sinatra/ping","image":"treeder/hello-sinatra", "type":"app", "cpath":"/ping"}' http://localhost:8080/api/v1/apps/myapp/routes
|
||||||
```
|
```
|
||||||
|
|
||||||
And test it out:
|
And test it out:
|
||||||
@@ -49,7 +57,7 @@ curl -i -X GET http://localhost:8080/sinatra?app=myapp
|
|||||||
You'all also get a custom URL like this when in production.
|
You'all also get a custom URL like this when in production.
|
||||||
|
|
||||||
```
|
```
|
||||||
appname.projectid.iron.computer
|
appname.iron.computer
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building/Testing
|
## Building/Testing
|
||||||
@@ -66,7 +74,7 @@ glide install
|
|||||||
Test it, the iron token and project id are for cache.
|
Test it, the iron token and project id are for cache.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" --rm -it --privileged -p 8080:8080 iron/gateway
|
docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" -e "CLOUDFLARE_EMAIL=treeder@gmail.com" -e "CLOUDFLARE_API_KEY=X" --rm -it --privileged -p 8080:8080 iron/gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
Push it:
|
Push it:
|
||||||
@@ -82,3 +90,12 @@ After deploying, running it with:
|
|||||||
```sh
|
```sh
|
||||||
docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" --name irongateway -it --privileged --net=host -p 8080:8080 -d --name irongateway iron/gateway
|
docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" --name irongateway -it --privileged --net=host -p 8080:8080 -d --name irongateway iron/gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## TODOS
|
||||||
|
|
||||||
|
* [ ] Check if image exists when registering the endpoint, not at run time
|
||||||
|
* [ ] Put stats into influxdb or something to show to user (requests, errors)
|
||||||
|
* [ ] Store recent logs for user.
|
||||||
|
* [ ] Allow env vars for config on the app and routes (routes override apps).
|
||||||
|
* [ ] Provide a base url for each app, eg: appname.userid.iron.computer
|
||||||
|
* [ ] Allow setting content-type on a route, then use that when responding
|
||||||
|
|||||||
12
dns.go
12
dns.go
@@ -7,8 +7,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/iron-io/go/common"
|
"github.com/iron-io/go/common"
|
||||||
"gopkg.in/inconshreveable/log15.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CloudFlareResult struct {
|
type CloudFlareResult struct {
|
||||||
@@ -30,7 +30,7 @@ func registerHost(w http.ResponseWriter, r *http.Request, app *App) bool {
|
|||||||
// WORKER_NAME.PROJECT_ID.iron.computer.
|
// WORKER_NAME.PROJECT_ID.iron.computer.
|
||||||
dnsHost := fmt.Sprintf("%v.%v.iron.computer", app.Name, 123)
|
dnsHost := fmt.Sprintf("%v.%v.iron.computer", app.Name, 123)
|
||||||
app.Dns = dnsHost
|
app.Dns = dnsHost
|
||||||
log15.Info("registering dns", "dnsname", dnsHost)
|
log.Info("registering dns", "dnsname", dnsHost)
|
||||||
|
|
||||||
if app.CloudFlareId == "" {
|
if app.CloudFlareId == "" {
|
||||||
// Tad hacky, but their go lib is pretty confusing.
|
// Tad hacky, but their go lib is pretty confusing.
|
||||||
@@ -53,7 +53,7 @@ func registerHost(w http.ResponseWriter, r *http.Request, app *App) bool {
|
|||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log15.Error("Could not register dns entry.", "err", err)
|
log.Error("Could not register dns entry.", "err", err)
|
||||||
common.SendError(w, 500, fmt.Sprint("Could not register dns entry.", err))
|
common.SendError(w, 500, fmt.Sprint("Could not register dns entry.", err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -61,14 +61,14 @@ func registerHost(w http.ResponseWriter, r *http.Request, app *App) bool {
|
|||||||
// todo: get error message from body for bad status code
|
// todo: get error message from body for bad status code
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
log15.Error("Could not register dns entry 2.", "code", resp.StatusCode, "body", string(body))
|
log.Error("Could not register dns entry 2.", "code", resp.StatusCode, "body", string(body))
|
||||||
common.SendError(w, 500, fmt.Sprint("Could not register dns entry 2. ", resp.StatusCode))
|
common.SendError(w, 500, fmt.Sprint("Could not register dns entry 2. ", resp.StatusCode))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
cfResult := CloudFlareResponse{}
|
cfResult := CloudFlareResponse{}
|
||||||
err = json.Unmarshal(body, &cfResult)
|
err = json.Unmarshal(body, &cfResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log15.Error("Could not parse DNS response.", "err", err, "code", resp.StatusCode, "body", string(body))
|
log.Error("Could not parse DNS response.", "err", err, "code", resp.StatusCode, "body", string(body))
|
||||||
common.SendError(w, 500, fmt.Sprint("Could not parse DNS response. ", resp.StatusCode))
|
common.SendError(w, 500, fmt.Sprint("Could not parse DNS response. ", resp.StatusCode))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -76,6 +76,6 @@ func registerHost(w http.ResponseWriter, r *http.Request, app *App) bool {
|
|||||||
app.CloudFlareId = cfResult.Result.Id
|
app.CloudFlareId = cfResult.Result.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
log15.Info("host registered successfully with cloudflare", "app", app)
|
log.Info("host registered successfully with cloudflare", "app", app)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
23
gateway.pem
Normal file
23
gateway.pem
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-----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-----
|
||||||
10
glide.lock
generated
10
glide.lock
generated
@@ -1,5 +1,5 @@
|
|||||||
hash: a104a522dc2ba982d25101330bbd5d44778565128f0cb09f34061c167921046c
|
hash: a104a522dc2ba982d25101330bbd5d44778565128f0cb09f34061c167921046c
|
||||||
updated: 2016-06-15T17:17:05.21953321-07:00
|
updated: 2016-06-17T14:27:42.156301621-07:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/amir/raidman
|
- name: github.com/amir/raidman
|
||||||
version: 91c20f3f475cab75bb40ad7951d9bbdde357ade7
|
version: 91c20f3f475cab75bb40ad7951d9bbdde357ade7
|
||||||
@@ -12,7 +12,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- statsd
|
- statsd
|
||||||
- name: github.com/dgrijalva/jwt-go
|
- name: github.com/dgrijalva/jwt-go
|
||||||
version: c04502f106d7c5b3fae17c5da49a1bbdd3006b3c
|
version: f0777076321ab64f6efc15a82d9d23b98539b943
|
||||||
- name: github.com/golang/protobuf
|
- name: github.com/golang/protobuf
|
||||||
version: 0c1f6d65b5a189c2250d10e71a5506f06f9fa0a0
|
version: 0c1f6d65b5a189c2250d10e71a5506f06f9fa0a0
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -29,7 +29,7 @@ imports:
|
|||||||
- semaphore
|
- semaphore
|
||||||
- serverutil
|
- serverutil
|
||||||
- name: github.com/iron-io/go
|
- name: github.com/iron-io/go
|
||||||
version: 277190779e20ad6bff386a5f7f6a8009d73fa475
|
version: 6b082f50f20cb0e0146bdf0ffbc6c07216eeea77
|
||||||
subpackages:
|
subpackages:
|
||||||
- common
|
- common
|
||||||
- common/httpshutdown
|
- common/httpshutdown
|
||||||
@@ -50,12 +50,14 @@ imports:
|
|||||||
version: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59
|
version: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59
|
||||||
- name: github.com/mattn/go-isatty
|
- name: github.com/mattn/go-isatty
|
||||||
version: 56b76bdf51f7708750eac80fa38b952bb9f32639
|
version: 56b76bdf51f7708750eac80fa38b952bb9f32639
|
||||||
|
- name: github.com/Sirupsen/logrus
|
||||||
|
version: f3cfb454f4c209e6668c95216c4744b8fddb2356
|
||||||
- name: github.com/vmihailenco/bufio
|
- name: github.com/vmihailenco/bufio
|
||||||
version: 24e7e48f60fc2d9e99e43c07485d9fff42051e66
|
version: 24e7e48f60fc2d9e99e43c07485d9fff42051e66
|
||||||
- name: github.com/vrischmann/envconfig
|
- name: github.com/vrischmann/envconfig
|
||||||
version: 9e6e1c4d3b73427d03118518603bb904d9c55236
|
version: 9e6e1c4d3b73427d03118518603bb904d9c55236
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: 3f122ce3dbbe488b7e6a8bdb26f41edec852a40b
|
version: d7bf3545bb0dacf009c535b3d3fbf53ac0a339ab
|
||||||
subpackages:
|
subpackages:
|
||||||
- proxy
|
- proxy
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type App struct {
|
|||||||
ProjectId string `json:"project_id"`
|
ProjectId string `json:"project_id"`
|
||||||
CloudFlareId string `json:"-"`
|
CloudFlareId string `json:"-"`
|
||||||
Dns string `json:"dns"`
|
Dns string `json:"dns"`
|
||||||
Routes []Route3 `json:"routes"`
|
Routes map[string]*Route3 `json:"routes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is for the new api gateway
|
// this is for the new api gateway
|
||||||
|
|||||||
140
router.go
140
router.go
@@ -11,20 +11,19 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/iron-io/go/common"
|
|
||||||
"github.com/iron-io/golog"
|
|
||||||
"github.com/iron-io/iron_go/cache"
|
|
||||||
"github.com/iron-io/iron_go/worker"
|
|
||||||
"gopkg.in/inconshreveable/log15.v2"
|
|
||||||
"log"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/iron-io/go/common"
|
||||||
|
"github.com/iron-io/iron_go/cache"
|
||||||
|
"github.com/iron-io/iron_go/worker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var config struct {
|
var config struct {
|
||||||
@@ -82,11 +81,12 @@ func main() {
|
|||||||
common.LoadConfigFile(configFile, &config)
|
common.LoadConfigFile(configFile, &config)
|
||||||
// common.SetLogging(common.LoggingConfig{To: config.Logging.To, Level: config.Logging.Level, Prefix: config.Logging.Prefix})
|
// common.SetLogging(common.LoggingConfig{To: config.Logging.To, Level: config.Logging.Level, Prefix: config.Logging.Prefix})
|
||||||
|
|
||||||
log.Println("config:", config)
|
// TODO: validate inputs, iron tokens, cloudflare stuff, etc
|
||||||
golog.Infoln("Starting up router version", version)
|
config.CloudFlare.Email = os.Getenv("CLOUDFLARE_EMAIL")
|
||||||
|
config.CloudFlare.AuthKey = os.Getenv("CLOUDFLARE_API_KEY")
|
||||||
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
log.Println("config:", config)
|
||||||
log.Println("Running on", runtime.NumCPU(), "CPUs")
|
log.Infoln("Starting up router version", version)
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
@@ -95,35 +95,34 @@ func main() {
|
|||||||
s2.Handle("/", &WorkerHandler{})
|
s2.Handle("/", &WorkerHandler{})
|
||||||
|
|
||||||
// dev:
|
// dev:
|
||||||
fmt.Println("Setting /test subrouter")
|
s := r.PathPrefix("/api").Subrouter()
|
||||||
s := r.PathPrefix("/test").Subrouter()
|
|
||||||
// production:
|
// production:
|
||||||
// s := r.Host("router.irondns.info").Subrouter()
|
// s := r.Host("router.irondns.info").Subrouter()
|
||||||
s.Handle("/1/projects/{project_id}/register", &Register{})
|
// s.Handle("/1/projects/{project_id}/register", &Register{})
|
||||||
s.Handle("/1/projects/{project_id}/apps", &NewApp{})
|
s.Handle("/v1/apps", &NewApp{})
|
||||||
s.HandleFunc("/1/projects/{project_id}/apps/{app_name}/routes", NewRoute)
|
s.HandleFunc("/v1/apps/{app_name}/routes", NewRoute)
|
||||||
s.HandleFunc("/ping", Ping)
|
s.HandleFunc("/ping", Ping)
|
||||||
s.HandleFunc("/version", Version)
|
s.HandleFunc("/version", Version)
|
||||||
s.Handle("/addworker", &WorkerHandler{})
|
// s.Handle("/addworker", &WorkerHandler{})
|
||||||
s.HandleFunc("/", Ping)
|
s.HandleFunc("/", Ping)
|
||||||
|
|
||||||
r.HandleFunc("/elb-ping-router", Ping) // for ELB health check
|
r.HandleFunc("/elb-ping-router", Ping) // for ELB health check
|
||||||
|
|
||||||
// for testing app responses, pass in app name, can use localhost
|
// for testing app responses, pass in app name, can use localhost
|
||||||
s4 := r.Queries("app", "").Subrouter()
|
s4 := r.Queries("app", "").Subrouter()
|
||||||
s4.HandleFunc("/appsr", Ping)
|
// s4.HandleFunc("/appsr", Ping)
|
||||||
s4.HandleFunc("/{rest:.*}", Run)
|
s4.HandleFunc("/{rest:.*}", Run)
|
||||||
s4.NotFoundHandler = http.HandlerFunc(Run)
|
s4.NotFoundHandler = http.HandlerFunc(Run)
|
||||||
|
|
||||||
s3 := r.Queries("rhost", "").Subrouter()
|
// s3 := r.Queries("rhost", "").Subrouter()
|
||||||
s3.HandleFunc("/", ProxyFunc2)
|
// s3.HandleFunc("/", ProxyFunc2)
|
||||||
|
|
||||||
// This is where all the main incoming traffic goes
|
// This is where all the main incoming traffic goes
|
||||||
r.NotFoundHandler = http.HandlerFunc(Run)
|
r.NotFoundHandler = http.HandlerFunc(Run)
|
||||||
|
|
||||||
http.Handle("/", r)
|
http.Handle("/", r)
|
||||||
port := 8080
|
port := 8080
|
||||||
golog.Infoln("Router started, listening and serving on port", port)
|
log.Infoln("Router started, listening and serving on port", port)
|
||||||
log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%v", port), nil))
|
log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%v", port), nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +132,10 @@ func ProxyFunc2(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ProxyFunc(w http.ResponseWriter, req *http.Request) {
|
func ProxyFunc(w http.ResponseWriter, req *http.Request) {
|
||||||
golog.Infoln("HOST:", req.Host)
|
log.Infoln("HOST:", req.Host)
|
||||||
host := strings.Split(req.Host, ":")[0]
|
host := strings.Split(req.Host, ":")[0]
|
||||||
rhost := req.FormValue("rhost")
|
rhost := req.FormValue("rhost")
|
||||||
golog.Infoln("rhost:", rhost)
|
log.Infoln("rhost:", rhost)
|
||||||
if rhost != "" {
|
if rhost != "" {
|
||||||
host = rhost
|
host = rhost
|
||||||
}
|
}
|
||||||
@@ -146,10 +145,10 @@ func ProxyFunc(w http.ResponseWriter, req *http.Request) {
|
|||||||
// 2) This host has active workers so we do the proxy
|
// 2) This host has active workers so we do the proxy
|
||||||
// 3) This host has no active workers so we queue one (or more) up and return a 503 or something with message that says "try again in a minute"
|
// 3) This host has no active workers so we queue one (or more) up and return a 503 or something with message that says "try again in a minute"
|
||||||
// route := routingTable[host]
|
// route := routingTable[host]
|
||||||
golog.Infoln("getting route for host:", host, "--")
|
log.Infoln("getting route for host:", host, "--")
|
||||||
route, err := getRoute(host)
|
route, err := getRoute(host)
|
||||||
golog.Infoln("route:", route)
|
log.Infoln("route:", route)
|
||||||
golog.Infoln("err:", err)
|
log.Infoln("err:", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendError(w, 400, fmt.Sprintln("Host not registered or error!", err))
|
common.SendError(w, 400, fmt.Sprintln("Host not registered or error!", err))
|
||||||
return
|
return
|
||||||
@@ -165,13 +164,13 @@ func ProxyFunc(w http.ResponseWriter, req *http.Request) {
|
|||||||
func serveEndpoint(w http.ResponseWriter, req *http.Request, route *Route) {
|
func serveEndpoint(w http.ResponseWriter, req *http.Request, route *Route) {
|
||||||
dlen := len(route.Destinations)
|
dlen := len(route.Destinations)
|
||||||
if dlen == 0 {
|
if dlen == 0 {
|
||||||
golog.Infoln("No workers running, starting new task.")
|
log.Infoln("No workers running, starting new task.")
|
||||||
startNewWorker(route)
|
startNewWorker(route)
|
||||||
common.SendError(w, 500, fmt.Sprintln("No workers running, starting them up..."))
|
common.SendError(w, 500, fmt.Sprintln("No workers running, starting them up..."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dlen < 3 {
|
if dlen < 3 {
|
||||||
golog.Infoln("Less than three workers running, starting a new task.")
|
log.Infoln("Less than three workers running, starting a new task.")
|
||||||
startNewWorker(route)
|
startNewWorker(route)
|
||||||
}
|
}
|
||||||
destIndex := rand.Intn(dlen)
|
destIndex := rand.Intn(dlen)
|
||||||
@@ -181,21 +180,21 @@ func serveEndpoint(w http.ResponseWriter, req *http.Request, route *Route) {
|
|||||||
destUrl, err := url.Parse(destUrlString2)
|
destUrl, err := url.Parse(destUrlString2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
removeDestination(route, destIndex, w)
|
removeDestination(route, destIndex, w)
|
||||||
golog.Infoln("error!", err)
|
log.Infoln("error!", err)
|
||||||
common.SendError(w, 500, fmt.Sprintln("Internal error occurred:", err))
|
common.SendError(w, 500, fmt.Sprintln("Internal error occurred:", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// todo: check destination runtime and remove it if it's expired so we don't send requests to an endpoint that is about to be killed
|
// todo: check destination runtime and remove it if it's expired so we don't send requests to an endpoint that is about to be killed
|
||||||
golog.Infoln("proxying to", destUrl)
|
log.Infoln("proxying to", destUrl)
|
||||||
proxy := NewSingleHostReverseProxy(destUrl)
|
proxy := NewSingleHostReverseProxy(destUrl)
|
||||||
err = proxy.ServeHTTP(w, req)
|
err = proxy.ServeHTTP(w, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("Error proxying!", err)
|
log.Infoln("Error proxying!", err)
|
||||||
etype := reflect.TypeOf(err)
|
etype := reflect.TypeOf(err)
|
||||||
golog.Infoln("err type:", etype)
|
log.Infoln("err type:", etype)
|
||||||
// can't figure out how to compare types so comparing strings.... lame.
|
// can't figure out how to compare types so comparing strings.... lame.
|
||||||
if true || strings.Contains(etype.String(), "net.OpError") { // == reflect.TypeOf(net.OpError{}) { // couldn't figure out a better way to do this
|
if true || strings.Contains(etype.String(), "net.OpError") { // == reflect.TypeOf(net.OpError{}) { // couldn't figure out a better way to do this
|
||||||
golog.Infoln("It's a network error so we're going to remove destination.")
|
log.Infoln("It's a network error so we're going to remove destination.")
|
||||||
removeDestination(route, destIndex, w)
|
removeDestination(route, destIndex, w)
|
||||||
serveEndpoint(w, req, route)
|
serveEndpoint(w, req, route)
|
||||||
return
|
return
|
||||||
@@ -203,28 +202,28 @@ func serveEndpoint(w http.ResponseWriter, req *http.Request, route *Route) {
|
|||||||
common.SendError(w, 500, fmt.Sprintln("Internal error occurred:", err))
|
common.SendError(w, 500, fmt.Sprintln("Internal error occurred:", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("Served!")
|
log.Infoln("Served!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeDestination(route *Route, destIndex int, w http.ResponseWriter) {
|
func removeDestination(route *Route, destIndex int, w http.ResponseWriter) {
|
||||||
golog.Infoln("Removing destination", destIndex, "from route:", route)
|
log.Infoln("Removing destination", destIndex, "from route:", route)
|
||||||
route.Destinations = append(route.Destinations[:destIndex], route.Destinations[destIndex+1:]...)
|
route.Destinations = append(route.Destinations[:destIndex], route.Destinations[destIndex+1:]...)
|
||||||
err := putRoute(route)
|
err := putRoute(route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("Couldn't update routing table:", err)
|
log.Infoln("Couldn't update routing table:", err)
|
||||||
common.SendError(w, 500, fmt.Sprintln("couldn't update routing table", err))
|
common.SendError(w, 500, fmt.Sprintln("couldn't update routing table", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("New route after remove destination:", route)
|
log.Infoln("New route after remove destination:", route)
|
||||||
// if len(route.Destinations) < 3 {
|
// if len(route.Destinations) < 3 {
|
||||||
// golog.Infoln("After network error, there are less than three destinations, so starting a new one. ")
|
// log.Infoln("After network error, there are less than three destinations, so starting a new one. ")
|
||||||
// // always want at least three running
|
// // always want at least three running
|
||||||
// startNewWorker(route)
|
// startNewWorker(route)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNewWorker(route *Route) error {
|
func startNewWorker(route *Route) error {
|
||||||
golog.Infoln("Starting a new worker")
|
log.Infoln("Starting a new worker")
|
||||||
// start new worker
|
// start new worker
|
||||||
payload := map[string]interface{}{
|
payload := map[string]interface{}{
|
||||||
"token": config.Iron.SuperToken,
|
"token": config.Iron.SuperToken,
|
||||||
@@ -238,7 +237,7 @@ func startNewWorker(route *Route) error {
|
|||||||
workerapi.Settings.UseConfigMap(payload)
|
workerapi.Settings.UseConfigMap(payload)
|
||||||
jsonPayload, err := json.Marshal(payload)
|
jsonPayload, err := json.Marshal(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("Couldn't marshal json!", err)
|
log.Infoln("Couldn't marshal json!", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
timeout := time.Second * time.Duration(1800+rand.Intn(600)) // a little random factor in here to spread out worker deaths
|
timeout := time.Second * time.Duration(1800+rand.Intn(600)) // a little random factor in here to spread out worker deaths
|
||||||
@@ -250,9 +249,9 @@ func startNewWorker(route *Route) error {
|
|||||||
tasks := make([]worker.Task, 1)
|
tasks := make([]worker.Task, 1)
|
||||||
tasks[0] = task
|
tasks[0] = task
|
||||||
taskIds, err := workerapi.TaskQueue(tasks...)
|
taskIds, err := workerapi.TaskQueue(tasks...)
|
||||||
golog.Infoln("Tasks queued.", taskIds)
|
log.Infoln("Tasks queued.", taskIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("Couldn't queue up worker!", err)
|
log.Infoln("Couldn't queue up worker!", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -267,13 +266,13 @@ func (r *Register) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
projectId := vars["project_id"]
|
projectId := vars["project_id"]
|
||||||
token := common.GetToken(req)
|
token := common.GetToken(req)
|
||||||
golog.Infoln("project_id:", projectId, "token:", token.Token)
|
log.Infoln("project_id:", projectId, "token:", token.Token)
|
||||||
|
|
||||||
route := Route{}
|
route := Route{}
|
||||||
if !common.ReadJSON(w, req, &route) {
|
if !common.ReadJSON(w, req, &route) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("body read into route:", route)
|
log.Infoln("body read into route:", route)
|
||||||
route.ProjectId = projectId
|
route.ProjectId = projectId
|
||||||
route.Token = token.Token
|
route.Token = token.Token
|
||||||
|
|
||||||
@@ -287,11 +286,11 @@ func (r *Register) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
// todo: do we need to close body?
|
// todo: do we need to close body?
|
||||||
err = putRoute(&route)
|
err = putRoute(&route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("couldn't register host:", err)
|
log.Infoln("couldn't register host:", err)
|
||||||
common.SendError(w, 400, fmt.Sprintln("Could not register host!", err))
|
common.SendError(w, 400, fmt.Sprintln("Could not register host!", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("registered route:", route)
|
log.Infoln("registered route:", route)
|
||||||
fmt.Fprintln(w, "Host registered successfully.")
|
fmt.Fprintln(w, "Host registered successfully.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,13 +303,13 @@ func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
projectId := vars["project_id"]
|
projectId := vars["project_id"]
|
||||||
// token := common.GetToken(req)
|
// token := common.GetToken(req)
|
||||||
golog.Infoln("project_id:", projectId)
|
log.Infoln("project_id:", projectId)
|
||||||
|
|
||||||
app := App{}
|
app := App{}
|
||||||
if !common.ReadJSON(w, req, &app) {
|
if !common.ReadJSON(w, req, &app) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("body read into app:", app)
|
log.Infoln("body read into app:", app)
|
||||||
app.ProjectId = projectId
|
app.ProjectId = projectId
|
||||||
|
|
||||||
_, err := getApp(app.Name)
|
_, err := getApp(app.Name)
|
||||||
@@ -319,9 +318,11 @@ func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.Routes = make(map[string]*Route3)
|
||||||
|
|
||||||
// create dns entry
|
// create dns entry
|
||||||
// TODO: Add project id to this. eg: appname.projectid.iron.computer
|
// TODO: Add project id to this. eg: appname.projectid.iron.computer
|
||||||
log15.Debug("Creating dns entry.")
|
log.Debug("Creating dns entry.")
|
||||||
regOk := registerHost(w, req, &app)
|
regOk := registerHost(w, req, &app)
|
||||||
if !regOk {
|
if !regOk {
|
||||||
return
|
return
|
||||||
@@ -330,11 +331,11 @@ func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
// todo: do we need to close body?
|
// todo: do we need to close body?
|
||||||
err = putApp(&app)
|
err = putApp(&app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("couldn't create app:", err)
|
log.Infoln("couldn't create app:", err)
|
||||||
common.SendError(w, 400, fmt.Sprintln("Could not create app!", err))
|
common.SendError(w, 400, fmt.Sprintln("Could not create app!", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("registered app:", app)
|
log.Infoln("registered app:", app)
|
||||||
v := map[string]interface{}{"app": app}
|
v := map[string]interface{}{"app": app}
|
||||||
common.SendSuccess(w, "App created successfully.", v)
|
common.SendSuccess(w, "App created successfully.", v)
|
||||||
}
|
}
|
||||||
@@ -344,13 +345,13 @@ func NewRoute(w http.ResponseWriter, req *http.Request) {
|
|||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
projectId := vars["project_id"]
|
projectId := vars["project_id"]
|
||||||
appName := vars["app_name"]
|
appName := vars["app_name"]
|
||||||
golog.Infoln("project_id:", projectId, "app_name", appName)
|
log.Infoln("project_id:", projectId, "app_name", appName)
|
||||||
|
|
||||||
route := Route3{}
|
route := &Route3{}
|
||||||
if !common.ReadJSON(w, req, &route) {
|
if !common.ReadJSON(w, req, &route) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("body read into route:", route)
|
log.Infoln("body read into route:", route)
|
||||||
|
|
||||||
// TODO: validate route
|
// TODO: validate route
|
||||||
|
|
||||||
@@ -360,14 +361,19 @@ func NewRoute(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Routes = append(app.Routes, route)
|
if route.Type == "" {
|
||||||
|
route.Type = "run"
|
||||||
|
}
|
||||||
|
|
||||||
|
// app.Routes = append(app.Routes, route)
|
||||||
|
app.Routes[route.Path] = route
|
||||||
err = putApp(app)
|
err = putApp(app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Errorln("Couldn't create route!:", err)
|
log.Errorln("Couldn't create route!:", err)
|
||||||
common.SendError(w, 400, fmt.Sprintln("Could not create route!", err))
|
common.SendError(w, 400, fmt.Sprintln("Could not create route!", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("Route created:", route)
|
log.Infoln("Route created:", route)
|
||||||
fmt.Fprintln(w, "Route created successfully.")
|
fmt.Fprintln(w, "Route created successfully.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,13 +382,13 @@ type WorkerHandler struct {
|
|||||||
|
|
||||||
// When a worker starts up, it calls this
|
// When a worker starts up, it calls this
|
||||||
func (wh *WorkerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (wh *WorkerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
golog.Infoln("AddWorker called!")
|
log.Infoln("AddWorker called!")
|
||||||
|
|
||||||
// get project id and token
|
// get project id and token
|
||||||
projectId := req.FormValue("project_id")
|
projectId := req.FormValue("project_id")
|
||||||
token := req.FormValue("token")
|
token := req.FormValue("token")
|
||||||
// codeName := req.FormValue("code_name")
|
// codeName := req.FormValue("code_name")
|
||||||
golog.Infoln("project_id:", projectId, "token:", token)
|
log.Infoln("project_id:", projectId, "token:", token)
|
||||||
|
|
||||||
// check header for what operation to perform
|
// check header for what operation to perform
|
||||||
routerHeader := req.Header.Get("Iron-Router")
|
routerHeader := req.Header.Get("Iron-Router")
|
||||||
@@ -394,28 +400,28 @@ func (wh *WorkerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// todo: do we need to close body?
|
// todo: do we need to close body?
|
||||||
golog.Infoln("Incoming body from worker:", r2)
|
log.Infoln("Incoming body from worker:", r2)
|
||||||
route, err := getRoute(r2.Host)
|
route, err := getRoute(r2.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendError(w, 400, fmt.Sprintln("This host is not registered!", err))
|
common.SendError(w, 400, fmt.Sprintln("This host is not registered!", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("ROUTE:", route)
|
log.Infoln("ROUTE:", route)
|
||||||
route.Destinations = append(route.Destinations, r2.Dest)
|
route.Destinations = append(route.Destinations, r2.Dest)
|
||||||
golog.Infoln("ROUTE new:", route)
|
log.Infoln("ROUTE new:", route)
|
||||||
err = putRoute(route)
|
err = putRoute(route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Infoln("couldn't register host:", err)
|
log.Infoln("couldn't register host:", err)
|
||||||
common.SendError(w, 400, fmt.Sprintln("Could not register host!", err))
|
common.SendError(w, 400, fmt.Sprintln("Could not register host!", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "Worker added")
|
fmt.Fprintln(w, "Worker added")
|
||||||
golog.Infoln("Worked added.")
|
log.Infoln("Worked added.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRoute(host string) (*Route, error) {
|
func getRoute(host string) (*Route, error) {
|
||||||
golog.Infoln("getRoute for host:", host)
|
log.Infoln("getRoute for host:", host)
|
||||||
rx, err := icache.Get(host)
|
rx, err := icache.Get(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -441,7 +447,7 @@ func putRoute(route *Route) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getApp(name string) (*App, error) {
|
func getApp(name string) (*App, error) {
|
||||||
golog.Infoln("getapp:", name)
|
log.Infoln("getapp:", name)
|
||||||
rx, err := icache.Get(name)
|
rx, err := icache.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
48
runner.go
48
runner.go
@@ -4,8 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/iron-io/go/common"
|
|
||||||
"github.com/iron-io/golog"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -13,7 +11,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/iron-io/go/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RunningApp struct {
|
type RunningApp struct {
|
||||||
@@ -31,15 +31,15 @@ func init() {
|
|||||||
|
|
||||||
func Run(w http.ResponseWriter, req *http.Request) {
|
func Run(w http.ResponseWriter, req *http.Request) {
|
||||||
fmt.Println("RUN!!!!")
|
fmt.Println("RUN!!!!")
|
||||||
golog.Infoln("HOST:", req.Host)
|
log.Infoln("HOST:", req.Host)
|
||||||
appName := req.FormValue("app")
|
appName := req.FormValue("app")
|
||||||
golog.Infoln("app_name", appName, "path:", req.URL.Path)
|
log.Infoln("app_name", appName, "path:", req.URL.Path)
|
||||||
if appName != "" {
|
if appName != "" {
|
||||||
// passed in the name
|
// passed in the name
|
||||||
} else {
|
} else {
|
||||||
host := strings.Split(req.Host, ":")[0]
|
host := strings.Split(req.Host, ":")[0]
|
||||||
appName = strings.Split(host, ".")[0]
|
appName = strings.Split(host, ".")[0]
|
||||||
golog.Infoln("app_name from host", appName)
|
log.Infoln("app_name from host", appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
app, err := getApp(appName)
|
app, err := getApp(appName)
|
||||||
@@ -47,7 +47,7 @@ func Run(w http.ResponseWriter, req *http.Request) {
|
|||||||
common.SendError(w, 400, fmt.Sprintln("This app does not exist. Please create app first.", err))
|
common.SendError(w, 400, fmt.Sprintln("This app does not exist. Please create app first.", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
golog.Infoln("app", app)
|
log.Infoln("app", app)
|
||||||
|
|
||||||
// find route
|
// find route
|
||||||
for _, el := range app.Routes {
|
for _, el := range app.Routes {
|
||||||
@@ -60,11 +60,11 @@ func Run(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if el.Type == "app" {
|
if el.Type == "app" {
|
||||||
DockerHost(&el, w)
|
DockerHost(el, w)
|
||||||
return
|
return
|
||||||
} else { // "run"
|
} else { // "run"
|
||||||
// TODO: timeout 59 seconds
|
// TODO: timeout 59 seconds
|
||||||
DockerRun(el.Image, w)
|
DockerRun(el.Image, w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,8 +73,18 @@ func Run(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use Docker utils from docker-job for this and a few others in here
|
// TODO: use Docker utils from docker-job for this and a few others in here
|
||||||
func DockerRun(image string, w http.ResponseWriter) {
|
func DockerRun(image string, w http.ResponseWriter, req *http.Request) {
|
||||||
cmd := exec.Command("docker", "run", "--rm", "-i", image)
|
|
||||||
|
payload, err := ioutil.ReadAll(req.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorln("Error reading request body")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.WithField("payload", "---"+string(payload)+"---").Infoln("incoming request")
|
||||||
|
log.WithField("image", image).Infoln("About to run using this image")
|
||||||
|
|
||||||
|
// TODO: swap all this out with Titan's running via API
|
||||||
|
cmd := exec.Command("docker", "run", "--rm", "-i", "-e", fmt.Sprintf("PAYLOAD=%v", string(payload)), image)
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -94,14 +104,18 @@ func DockerRun(image string, w http.ResponseWriter) {
|
|||||||
|
|
||||||
log.Printf("Waiting for command to finish...")
|
log.Printf("Waiting for command to finish...")
|
||||||
if err = cmd.Wait(); err != nil {
|
if err = cmd.Wait(); err != nil {
|
||||||
// this probably shouldn't be fatal? test with iron/error image
|
// job failed
|
||||||
log.Fatal(err)
|
log.Infoln("job finished with err:", err)
|
||||||
|
log.WithFields(log.Fields{"metric": "run.errors", "value": 1, "type": "count"}).Infoln("failed run")
|
||||||
|
// TODO: wrap error in json "error": buff
|
||||||
|
} else {
|
||||||
|
log.Infoln("Docker ran successfully:", b.String())
|
||||||
|
// print
|
||||||
|
log.WithFields(log.Fields{"metric": "run.success", "value": 1, "type": "count"}).Infoln("successful run")
|
||||||
}
|
}
|
||||||
log.WithFields(log.Fields{"metric": "ran", "value": 1, "type": "count"}).Infoln("")
|
log.WithFields(log.Fields{"metric": "run", "value": 1, "type": "count"}).Infoln("job ran")
|
||||||
log.Printf("Command finished with error: %v", err)
|
|
||||||
buff.Flush()
|
buff.Flush()
|
||||||
golog.Infoln("Docker ran successfully:", b.String())
|
fmt.Fprintln(w, string(bytes.Trim(b.Bytes(), "\x00")))
|
||||||
fmt.Fprintln(w, b.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerHost(el *Route3, w http.ResponseWriter) {
|
func DockerHost(el *Route3, w http.ResponseWriter) {
|
||||||
@@ -120,8 +134,8 @@ func DockerHost(el *Route3, w http.ResponseWriter) {
|
|||||||
// TODO: Need to catch interrupt and stop all containers that are started, see devo/dj for how to do this
|
// TODO: Need to catch interrupt and stop all containers that are started, see devo/dj for how to do this
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
|
||||||
// TODO: What if the app fails to start? Don't want to keep starting the container
|
// TODO: What if the app fails to start? Don't want to keep starting the container
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: check if it's still running?
|
// TODO: check if it's still running?
|
||||||
// TODO: if ra.terminated, then start new container?
|
// TODO: if ra.terminated, then start new container?
|
||||||
|
|||||||
Reference in New Issue
Block a user