Runs docker containers!!!

This commit is contained in:
Travis Reeder
2015-10-09 18:22:32 -07:00
parent cc5e7ac2b2
commit 3aeaf48128
5 changed files with 217 additions and 23 deletions

2
.gitignore vendored
View File

@@ -6,3 +6,5 @@ dj.cluster.*.json
script.tar.gz
router
app.zip
/app
vendor/

8
curlcmds.txt Normal file
View File

@@ -0,0 +1,8 @@
make app:
curl -H "Content-Type: application/json" -X POST -d '{"name":"myapp","password":"xyz"}' http://localhost:8080/test/1/projects/123/apps
register route:
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
get route:
curl -i -X GET http://localhost:8080/hello.rb?app=myapp

30
models.go Normal file
View File

@@ -0,0 +1,30 @@
package main
type Route struct {
// TODO: Change destinations to a simple cache so it can expire entries after 55 minutes (the one we use in common?)
Host string `json:"host"`
Destinations []string `json:"destinations"`
ProjectId string `json:"project_id"`
Token string `json:"token"` // store this so we can queue up new workers on demand
CodeName string `json:"code_name"`
}
// for adding new hosts
type Route2 struct {
Host string `json:"host"`
Dest string `json:"dest"`
}
// An app is that base object for api gateway
type App struct {
Name string `json:"name"`
ProjectId string `json:"project_id"`
Routes []Route3 `json:"routes"`
}
// this is for the new api gateway
type Route3 struct {
Path string `json:"path"`
Image string `json:"image"`
Type string `json:"type"`
}

137
router.go
View File

@@ -13,7 +13,6 @@ import (
"fmt"
"github.com/gorilla/mux"
"github.com/iron-io/go/common"
"github.com/iron-io/go/common/auth/apiauth"
"github.com/iron-io/golog"
"github.com/iron-io/iron_go/cache"
"github.com/iron-io/iron_go/worker"
@@ -47,34 +46,19 @@ var config struct {
}
}
var version = "0.0.17"
var version = "0.0.19"
//var routingTable = map[string]*Route{}
var icache = cache.New("routing-table")
var (
ironAuth common.Auth
ironAuth common.Auther
)
func init() {
}
type Route struct {
// TODO: Change destinations to a simple cache so it can expire entries after 55 minutes (the one we use in common?)
Host string `json:"host"`
Destinations []string `json:"destinations"`
ProjectId string `json:"project_id"`
Token string `json:"token"` // store this so we can queue up new workers on demand
CodeName string `json:"code_name"`
}
// for adding new hosts
type Route2 struct {
Host string `json:"host"`
Dest string `json:"dest"`
}
func main() {
var configFile string
@@ -90,15 +74,15 @@ func main() {
configFile = "config_" + env + ".json"
}
common.LoadConfig(configFile, &config)
common.SetLogging(common.LoggingConfig{To: config.Logging.To, Level: config.Logging.Level, Prefix: config.Logging.Prefix})
common.LoadConfigFile(configFile, &config)
// common.SetLogging(common.LoggingConfig{To: config.Logging.To, Level: config.Logging.Level, Prefix: config.Logging.Prefix})
golog.Infoln("Starting up router version", version)
runtime.GOMAXPROCS(runtime.NumCPU())
log.Println("Running on", runtime.NumCPU(), "CPUs")
ironAuth = apiauth.NewAPIAuth(config.Iron.AuthHost)
// ironAuth = apiauth.New(config.Iron.AuthHost)
cacheConfigMap := map[string]interface{}{
"token": config.Cache.Token,
@@ -115,8 +99,14 @@ func main() {
s2 := r.Headers("Iron-Router", "").Subrouter()
s2.Handle("/", &WorkerHandler{})
s := r.Host("router.irondns.info").Subrouter()
s.Handle("/1/projects/{project_id:[0-9a-fA-F]{24}}/register", common.AuthWrap(ironAuth, &Register{}))
// dev:
fmt.Println("Setting /test subrouter")
s := r.PathPrefix("/test").Subrouter()
// production:
// s := r.Host("router.irondns.info").Subrouter()
s.Handle("/1/projects/{project_id}/register", &Register{})
s.Handle("/1/projects/{project_id}/apps", &NewApp{})
s.HandleFunc("/1/projects/{project_id}/apps/{app_name}/routes", NewRoute)
s.HandleFunc("/ping", Ping)
s.HandleFunc("/version", Version)
s.Handle("/addworker", &WorkerHandler{})
@@ -125,6 +115,13 @@ func main() {
r.HandleFunc("/elb-ping-router", Ping) // for ELB health check
// Now for everyone else:
// r.HandleFunc("/", ProxyFunc)
// for testing app responses, pass in app name
s4 := r.Queries("app", "").Subrouter()
s4.HandleFunc("/appsr", Ping)
s4.HandleFunc("/{rest:.*}", Run)
s4.NotFoundHandler = http.HandlerFunc(Run)
s3 := r.Queries("rhost", "").Subrouter()
s3.HandleFunc("/", ProxyFunc2)
r.NotFoundHandler = http.HandlerFunc(ProxyFunc)
@@ -303,6 +300,74 @@ func (r *Register) ServeHTTP(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, "Host registered successfully.")
}
type NewApp struct{}
// This registers a new host
func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) {
log.Println("NewApp called!")
vars := mux.Vars(req)
projectId := vars["project_id"]
// token := common.GetToken(req)
golog.Infoln("project_id:", projectId)
app := App{}
if !common.ReadJSON(w, req, &app) {
return
}
golog.Infoln("body read into app:", app)
app.ProjectId = projectId
_, err := getApp(app.Name)
if err == nil {
common.SendError(w, 400, fmt.Sprintln("This app already exists. If you believe this is in error, please contact support@iron.io to resolve the issue.", err))
return
// route = &Route{}
}
// todo: do we need to close body?
err = putApp(&app)
if err != nil {
golog.Infoln("couldn't create app:", err)
common.SendError(w, 400, fmt.Sprintln("Could not create app!", err))
return
}
golog.Infoln("registered app:", app)
fmt.Fprintln(w, "App created successfully.")
}
func NewRoute(w http.ResponseWriter, req *http.Request) {
fmt.Println("NewRoute")
vars := mux.Vars(req)
projectId := vars["project_id"]
appName := vars["app_name"]
golog.Infoln("project_id:", projectId, "app_name", appName)
route := Route3{}
if !common.ReadJSON(w, req, &route) {
return
}
golog.Infoln("body read into route:", route)
// TODO: validate route
app, err := getApp(appName)
if err != nil {
common.SendError(w, 400, fmt.Sprintln("This app does not exist. Please create app first.", err))
return
}
app.Routes = append(app.Routes, route)
err = putApp(app)
if err != nil {
golog.Errorln("Couldn't create route!:", err)
common.SendError(w, 400, fmt.Sprintln("Could not create route!", err))
return
}
golog.Infoln("Route created:", route)
fmt.Fprintln(w, "Route created successfully.")
}
type WorkerHandler struct {
}
@@ -372,6 +437,32 @@ func putRoute(route *Route) error {
return err
}
func getApp(name string) (*App, error) {
golog.Infoln("getapp:", name)
rx, err := icache.Get(name)
if err != nil {
return nil, err
}
rx2 := []byte(rx.(string))
app := App{}
err = json.Unmarshal(rx2, &app)
if err != nil {
return nil, err
}
return &app, err
}
func putApp(app *App) error {
item := cache.Item{}
v, err := json.Marshal(app)
if err != nil {
return err
}
item.Value = string(v)
err = icache.Put(app.Name, &item)
return err
}
func Ping(w http.ResponseWriter, req *http.Request) {
fmt.Fprintln(w, "pong")
}

63
runner.go Normal file
View File

@@ -0,0 +1,63 @@
package main
import (
"bufio"
"bytes"
"fmt"
// "github.com/gorilla/mux"
"github.com/iron-io/go/common"
"github.com/iron-io/golog"
"io"
"log"
"net/http"
"os/exec"
)
func Run(w http.ResponseWriter, req *http.Request) {
fmt.Println("RUN!!!!")
// vars := mux.Vars(req)
appName := req.FormValue("app")
golog.Infoln("app_name", appName, "path:", req.URL.Path)
app, err := getApp(appName)
if err != nil {
common.SendError(w, 400, fmt.Sprintln("This app does not exist. Please create app first.", err))
return
}
golog.Infoln("app", app)
var b bytes.Buffer
buff := bufio.NewWriter(&b)
// find route
for _, el := range app.Routes {
// TODO: copy/use gorilla's pattern matching here
if el.Path == req.URL.Path {
// Boom, run it!
cmd := exec.Command("docker", "run", "--rm", "-i", el.Image)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// buff := bufio.NewWriter()
go io.Copy(buff, stdout) // <---- commented out because we will print out with buff.Scan()
go io.Copy(buff, stderr)
log.Printf("Waiting for command to finish...")
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
log.Printf("Command finished with error: %v", err)
buff.Flush()
}
}
golog.Infoln("Docker ran successfully:", b.String())
fmt.Fprintln(w, b.String())
}