From f08114c91d36773b25b7792aaabe4ad96beeffb6 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Tue, 20 Oct 2015 14:02:28 -0700 Subject: [PATCH] Boom ditty! Makes dns entry now. --- README.md | 14 ++++--- config_development.json | 6 ++- dns.go | 81 ++++++----------------------------------- models.go | 8 ++-- router.go | 61 +++++++++++-------------------- runner.go | 12 +++++- 6 files changed, 62 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index a5103f810..3af8e29a7 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ - -PROBABLY NEEDS TO BE DOCKER IN DOCKER FOR IT TO WORK SMOOTHLY, MAYBE DROP THE DJ GO RUN THING -AND DO IT NORMALLY. - # MicroServices Gateway / API Gateway First things first, register an app: @@ -71,10 +67,18 @@ Test it, the iron token and project id are for cache. docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" --rm -it --privileged --net=host -p 8080:8080 iron/gateway ``` +Push it: + +```sh +docker push iron/gateway +``` + +Get it on a server and point router.iron.computer (on cloudflare) to the machine. + After deploying, running it with: ```sh -docker run -e "IRON_TOKEN=GP8cqlKSrcpmqeR8x9WKD4qSAss" -e "IRON_PROJECT_ID=4fd2729368a0197d1102056b" --name irongateway -it --privileged --net=host -p 8080:8080 -d 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 # Previous version: diff --git a/config_development.json b/config_development.json index e0f74a85a..e381666db 100644 --- a/config_development.json +++ b/config_development.json @@ -14,5 +14,9 @@ "to": "papertrail", "level": "debug", "prefix": "router_staging" - } + }, + "cloudflare": { + "email": "treeder@gmail.com", + "auth_key": "f94272c543f19f8fad0f4f5b3e2ddb74ad929" + } } diff --git a/dns.go b/dns.go index 013ba1d15..b454560f7 100644 --- a/dns.go +++ b/dns.go @@ -8,8 +8,6 @@ import ( "strings" "github.com/iron-io/go/common" - "github.com/iron-io/go/swapi/backend" - "github.com/iron-io/iron_go/cache" "gopkg.in/inconshreveable/log15.v2" ) @@ -27,40 +25,23 @@ the routing table. Backend runners know this too. This will also create a dns entry for the worker in iron.computer. */ -func registerHost(w http.ResponseWriter, r *http.Request, code *backend.Code) bool { - dnsHost := fmt.Sprintf("%v.%v.iron.computer", strings.Replace(code.Name, " ", "-", -1), code.ProjectId.Hex()) - log15.Info("registering host", "host", code.Host, "ironhost", dnsHost) +func registerHost(w http.ResponseWriter, r *http.Request, app *App) bool { + // Give it an iron.computer entry with format: + // WORKER_NAME.PROJECT_ID.iron.computer. + dnsHost := fmt.Sprintf("%v.%v.iron.computer", app.Name, 123) + app.Dns = dnsHost + log15.Info("registering dns", "dnsname", dnsHost) - code.Host = &dnsHost - route, err := getRoute(code) - if err == nil { - if route.ProjectId != code.ProjectId.Hex() { - // somebody else already register this host - common.SendError(w, 400, fmt.Sprint("This host is already registered. If you believe this is in error, please contact support@iron.io to resolve the issue.", err)) - return false - } - } - if route == nil { - route = &backend.Route{ - CodeId: code.Id.Hex(), - Host: dnsHost, - ProjectId: code.ProjectId.Hex(), - CodeName: code.Name, - } - } - - if route.CloudFlareId == "" { - // And give it an iron.computer entry too with format: - // WORKER_NAME.PROJECT_ID.iron.computer. + if app.CloudFlareId == "" { // Tad hacky, but their go lib is pretty confusing. cfMethod := "POST" cfUrl := "https://api.cloudflare.com/client/v4/zones/29a42a6c6b9b2ed4b843b78d65b8af89/dns_records" - if route.CloudFlareId != "" { + if app.CloudFlareId != "" { // Have this here in case we need to support updating the entry. If we do this, is how: cfMethod = "PUT" - cfUrl = cfUrl + "/" + route.CloudFlareId + cfUrl = cfUrl + "/" + app.CloudFlareId } - cfbody := "{\"type\":\"CNAME\",\"name\":\"" + dnsHost + "\",\"content\":\"router.iron.io\",\"ttl\":120}" + cfbody := "{\"type\":\"CNAME\",\"name\":\"" + dnsHost + "\",\"content\":\"router.iron.computer\",\"ttl\":120}" client := &http.Client{} // todo: is default client fine? req, err := http.NewRequest( cfMethod, @@ -92,47 +73,9 @@ func registerHost(w http.ResponseWriter, r *http.Request, code *backend.Code) bo return false } fmt.Println("cfresult:", cfResult) - route.CloudFlareId = cfResult.Result.Id + app.CloudFlareId = cfResult.Result.Id } - // Now store it - // todo: do we even need to update the route after the first time?? - err = putRoute(route) - if err != nil { - log15.Error("Could not register host.", "err", err) - common.SendError(w, 500, fmt.Sprint("Could not register host.", err)) - return false - } - - log15.Info("host registered successfully", "route", route) + log15.Info("host registered successfully with cloudflare", "app", app) return true } - -func getRoute(code *backend.Code) (*backend.Route, error) { - log15.Info("in getRoute", "icache_settings", icache.Settings, "key", *code.Host) - rx, err := icache.Get(*code.Host) - if err != nil { - return nil, err - } - rx2 := []byte(rx.(string)) - var route backend.Route - err = json.Unmarshal(rx2, &route) - if err != nil { - return nil, err - } - return &route, err -} - -func putRoute(route *backend.Route) error { - log15.Info("in putRoute", "icache_settings", icache.Settings) - item := cache.Item{} - v, err := json.Marshal(route) - if err != nil { - return err - } - item.Value = string(v) - log15.Info("about to put route", "route", route, "host", route.Host) - // todo: put some kind of reasonable expiry on this (a month or two) - err = icache.Put(route.Host, &item) - return err -} diff --git a/models.go b/models.go index 2b5a991b9..682d62394 100644 --- a/models.go +++ b/models.go @@ -17,9 +17,11 @@ type Route2 struct { // 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"` + Name string `json:"name"` + ProjectId string `json:"project_id"` + CloudFlareId string `json:"-"` + Dns string `json:"dns"` + Routes []Route3 `json:"routes"` } // this is for the new api gateway diff --git a/router.go b/router.go index 1ab4c34fe..4e1c43dbc 100644 --- a/router.go +++ b/router.go @@ -16,6 +16,7 @@ import ( "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" "net/http" @@ -27,6 +28,10 @@ import ( ) var config struct { + CloudFlare struct { + Email string `json:"email"` + AuthKey string `json:"auth_key"` + } `json:"cloudflare"` Cache struct { Host string `json:"host"` Token string `json:"token"` @@ -77,22 +82,12 @@ func main() { common.LoadConfigFile(configFile, &config) // common.SetLogging(common.LoggingConfig{To: config.Logging.To, Level: config.Logging.Level, Prefix: config.Logging.Prefix}) + log.Println("config:", config) golog.Infoln("Starting up router version", version) runtime.GOMAXPROCS(runtime.NumCPU()) log.Println("Running on", runtime.NumCPU(), "CPUs") - // ironAuth = apiauth.New(config.Iron.AuthHost) - - // cacheConfigMap := map[string]interface{}{ - // "token": config.Cache.Token, - // "project_id": config.Cache.ProjectId, - // } - // if config.Cache.Host != "" { - // cacheConfigMap["host"] = config.Cache.Host - // } - // icache.Settings.UseConfigMap(cacheConfigMap) - r := mux.NewRouter() // This has to stay above the r.Host() one. @@ -113,10 +108,8 @@ func main() { s.HandleFunc("/", Ping) 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 + // for testing app responses, pass in app name, can use localhost s4 := r.Queries("app", "").Subrouter() s4.HandleFunc("/appsr", Ping) s4.HandleFunc("/{rest:.*}", Run) @@ -124,7 +117,9 @@ func main() { s3 := r.Queries("rhost", "").Subrouter() s3.HandleFunc("/", ProxyFunc2) - r.NotFoundHandler = http.HandlerFunc(ProxyFunc) + + // This is where all the main incoming traffic goes + r.NotFoundHandler = http.HandlerFunc(Run) http.Handle("/", r) port := 8080 @@ -306,28 +301,6 @@ type NewApp struct{} func (r *NewApp) ServeHTTP(w http.ResponseWriter, req *http.Request) { log.Println("NewApp called!") - -PUT THIS IN HERE -if code.Host != params.Host { - log15.Debug("Host passed in.", "host", params.Host) - update = true - // todo: verify properly formatted host - // todo: delete/unregister old host if it was something else - // todo: don't register if it's blank host - // todo: this should call the register endpoint on the router rather than talking directly to IronCache - // todo: also, unregister should be added to router to remove endpoints. - if params.Host != nil && *params.Host != "" { - regOk := registerHost(w, r, code) - if !regOk { - return - } - // TODO: queue up 1 task for this worker to get things started - } else { - // todo: need a way to remove code.host/disable incoming - } - } - - vars := mux.Vars(req) projectId := vars["project_id"] // token := common.GetToken(req) @@ -342,9 +315,16 @@ if code.Host != params.Host { _, 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)) + common.SendError(w, 400, fmt.Sprintln("An app with this name already exists.", err)) + return + } + + // create dns entry + // TODO: Add project id to this. eg: appname.projectid.iron.computer + log15.Debug("Creating dns entry.") + regOk := registerHost(w, req, &app) + if !regOk { return - // route = &Route{} } // todo: do we need to close body? @@ -355,7 +335,8 @@ if code.Host != params.Host { return } golog.Infoln("registered app:", app) - fmt.Fprintln(w, "App created successfully.") + v := map[string]interface{}{"app": app} + common.SendSuccess(w, "App created successfully.", v) } func NewRoute(w http.ResponseWriter, req *http.Request) { diff --git a/runner.go b/runner.go index 7cd0a10c6..3a25a4ba8 100644 --- a/runner.go +++ b/runner.go @@ -14,6 +14,7 @@ import ( "net/http" "os" "os/exec" + "strings" ) type RunningApp struct { @@ -31,9 +32,16 @@ func init() { func Run(w http.ResponseWriter, req *http.Request) { fmt.Println("RUN!!!!") - // vars := mux.Vars(req) + golog.Infoln("HOST:", req.Host) appName := req.FormValue("app") golog.Infoln("app_name", appName, "path:", req.URL.Path) + if appName != "" { + // passed in the name + } else { + host := strings.Split(req.Host, ":")[0] + appName = strings.Split(host, ".")[0] + golog.Infoln("app_name from host", appName) + } app, err := getApp(appName) if err != nil { @@ -110,7 +118,7 @@ func Run(w http.ResponseWriter, req *http.Request) { go io.Copy(buff, stderr) log.Printf("Waiting for command to finish...") - if err := cmd.Wait(); err != nil { + if err = cmd.Wait(); err != nil { log.Fatal(err) } log.Printf("Command finished with error: %v", err)