Ejemplo n.º 1
0
func NewAPI() *API {
	m := martini.Classic()
	m.Use(render.Renderer())
	m.Use(cors.Allow(&cors.Options{
		AllowOrigins:  []string{"*"},
		AllowMethods:  []string{"POST", "GET"},
		ExposeHeaders: []string{"Content-Length"},
	}))
	m.Use(staticbin.Static("web", Asset))
	return &API{m}
}
Ejemplo n.º 2
0
func main() {
	var serverPort int
	var localhost bool

	flag.StringVar(&ledgerFileName, "f", "", "Ledger file name (*Required).")
	flag.StringVar(&reportConfigFileName, "r", "", "Report config file name (*Required).")
	flag.IntVar(&serverPort, "port", 8056, "Port to listen on.")
	flag.BoolVar(&localhost, "localhost", false, "Listen on localhost only.")

	flag.Parse()

	if len(ledgerFileName) == 0 || len(reportConfigFileName) == 0 {
		flag.Usage()
		return
	}

	go func() {
		for {
			var rLoadData reportConfigStruct
			toml.DecodeFile(reportConfigFileName, &rLoadData)
			reportConfigData = rLoadData
			time.Sleep(time.Minute * 5)
		}
	}()

	m := martini.Classic()
	m.Use(gzip.All())
	m.Use(staticbin.Static("public", Asset))

	m.Get("/ledger", ledgerHandler)
	m.Get("/accounts", accountsHandler)
	m.Get("/account/:accountName", accountHandler)
	m.Get("/report/:reportName", reportHandler)
	m.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/accounts", http.StatusFound)
	})

	fmt.Println("Listening on port", serverPort)
	listenAddress := ""
	if localhost {
		listenAddress = fmt.Sprintf("127.0.0.1:%d", serverPort)
	} else {
		listenAddress = fmt.Sprintf(":%d", serverPort)
	}
	http.ListenAndServe(listenAddress, m)
}
Ejemplo n.º 3
0
func main() {
	logging.SetFormatter(format)

	cfg, err := config.NewConfig(&config.FlagLoader{})
	if err != nil {
		panic(err)
	}

	var (
		cache    = cc.NewFileCache()
		buildbot = bb.NewBuildbotApi(cfg.BuildBotUrl, pool.NewRequestPool(), log)

		indexHandler    = handler.NewIndexHandler()
		buildersHandler = handler.NewBuildersHandler(cfg, buildbot, cache, log)
	)

	router := martini.Classic()
	router.Use(staticbin.Static("static/assets", Asset))
	router.Use(render.RendererBin(Asset, AssetNames(), render.Options{
		Directory:  "static/templates",
		Layout:     "layout",
		Extensions: []string{".tmpl", ".html"},
		Charset:    "UTF-8",
		IndentJSON: true,
		Funcs: []template.FuncMap{
			{
				"refreshSec": func() string {
					return strconv.Itoa(cfg.RefreshSec)
				},
				"buildbotUrl": func() string {
					return buildbot.GetUrl()
				},
				"hashedUrl": func() string {
					return cfg.HashedUrl
				},
			},
		},
	}))

	router.Get("/", indexHandler.ServeHTTP)
	router.Get("/builders", buildersHandler.GetBuilders)
	router.Get("/builder/:id", buildersHandler.GetBuilder)

	router.Run()
}
Ejemplo n.º 4
0
// Server Launcher
func Server() {
	m := martini.Classic()
	m.Use(staticbin.Static("web/static", Asset))
	m.Use(render.Renderer(render.Options{
		Directory:  "web/templates",
		Extensions: []string{".tmpl", ".html"},
		Funcs:      funcs, // Specify helper function maps for templates to access.
	}))

	m.Get("/", func(r render.Render) {
		p1 := game.NewPlay("player1")
		p2 := game.NewPlay("player2")
		players := [2]*game.Play{p1, p2}
		var game game.Game

		game.Start(players)

		r.HTML(200, "index", game.GetGrids())
	})
	m.Run()
}
Ejemplo n.º 5
0
func NewRouter(c *container.ContainerBag) *martini.ClassicMartini {
	var (
		indexHandler    = handler.NewIndexHandler(c)
		buildersHandler = handler.NewBuildersHandler(c)
	)

	router := martini.Classic()
	router.Use(staticbin.Static("static/assets", Asset))
	router.Use(render.RendererBin(Asset, AssetNames(), render.Options{
		Directory:  "static/templates",
		Layout:     "layout",
		Extensions: []string{".tmpl", ".html"},
		Charset:    "UTF-8",
		IndentJSON: true,
		Funcs: []template.FuncMap{
			{
				"genericSize": func() string {
					return c.GenericSize
				},
				"buildbotUrl": func() string {
					return c.BuildBotUrl
				},
				"hashedUrl": func() string {
					return c.HashedUrl
				},
				"displayEmptyBuilder": func() bool {
					return c.EmptyBuilders
				},
			},
		},
	}))

	router.Get("/", indexHandler.ServeHTTP)
	router.Get("/builders", buildersHandler.ServeHTTP)

	handler.AddWs(router, c)

	return router
}
Ejemplo n.º 6
0
func main() {

	flag.StringVar(&appDir, "app-dir", "", "Path to grafana installation")
	flag.StringVar(&dbDir, "db-dir", "dashboards", "Path to dashboard storage dir")
	flag.StringVar(&authDomain, "auth-domain", "", "OAuth2 domain users must authenticated from (mydomain.com)")
	flag.StringVar(&basicAuth, "auth", "", "Basic auth username (user:pw)")
	flag.StringVar(&sessionSecret, "session-secret", defaultSessionSecret, "Session secret key")
	flag.StringVar(&httpAddr, "http-addr", ":8080", "HTTP Server bind address")
	flag.StringVar(&httpsAddr, "https-addr", ":8443", "HTTPS Server bind address")
	flag.StringVar(&graphiteURL, "graphite-url", "", "Graphite URL (http://host:port)")
	flag.StringVar(&influxDBURL, "influxdb-url", "", "InfluxDB URL (http://host:8086/db/mydb)")
	flag.StringVar(&influxDBUser, "influxdb-user", "", "InfluxDB username")
	flag.StringVar(&influxDBPass, "influxdb-pass", "", "InfluxDB password")
	flag.StringVar(&openTSDBUrl, "opentsdb-url", "", "OpenTSDB URL (http://host:4242)")
	flag.StringVar(&sslCert, "ssl-cert", "", "SSL cert (PEM formatted)")
	flag.StringVar(&sslKey, "ssl-key", "", "SSL key (PEM formatted)")
	flag.StringVar(&hostAddr, "host-addr", "http://localhost:8080", "Public server address (http://mydomain.com)")
	flag.StringVar(&googleClientID, "google-client-id", "", "Google Oauth2 Client ID")
	flag.StringVar(&googleClientSecret, "google-client-secret", "", "Google Oauth2 Client Sercret")

	flag.BoolVar(&version, "version", false, "show version")
	flag.Parse()

	if version {
		println(buildVersion)
		return
	}

	if sessionSecret == defaultSessionSecret {
		log.Printf("WARN: Session secret key is using the hard-coded default. Use -session-secret <value> for a live deployment.\n")
	}

	if graphiteURL == "" && influxDBURL == "" && openTSDBUrl == "" {
		fmt.Printf("No graphite-url, influxdb-url or opentsdb-url specified.\nUse -graphite-url http://host:port or -influxdb-url http://host:8086/db/mydb or -opentsdb-url http://host:4242\n")
		return
	}

	log.Printf("Starting gofana %s", buildVersion)
	if _, err := os.Stat(dbDir); os.IsNotExist(err) {
		fmt.Printf("%s does not exist. Creating.\n", dbDir)
		err := os.Mkdir(dbDir, 0766)
		if err != nil {
			fmt.Printf("ERROR: %s\n", err)
			return
		}
	}

	db = &DashboardRepository{Dir: dbDir}
	err := db.Load()
	if err != nil {
		fmt.Printf("ERROR: %s\n", err)
		return
	}

	logger := log.New(os.Stderr, "", log.LstdFlags)
	r := martini.NewRouter()
	m := martini.New()
	m.Map(logger)
	m.Use(martini.Recovery())
	m.MapTo(r, (*martini.Routes)(nil))
	m.Action(r.Handle)

	if sslCert != "" && sslKey != "" {
		m.Use(secure.Secure(secure.Options{}))
	}

	b := make([]byte, 32)
	_, err = rand.Read(b)
	if err != nil {
		fmt.Printf("ERROR: %s\n", err)
		return
	}

	m.Use(sessions.Sessions("session", sessions.NewCookieStore([]byte(sessionSecret))))
	if oauthEnabled() {

		if authDomain == "" {
			fmt.Println("ERROR: No -auth-domain specified.  Cannot authenticate with OAuth2.\n")
			return
		}

		gomniauth.SetSecurityKey(signature.RandomKey(64))
		providers := gomniauth.WithProviders()

		if googleOauthEnabled() {
			providers.Add(google.New(googleClientID, googleClientSecret, fmt.Sprintf("%s/google/oauth2callback", hostAddr)))
		}
		m.Use(loginRequired)
	}

	m.Use(addCorsHeaders)
	m.Use(render.Renderer())

	if basicAuth != "" && strings.Contains(basicAuth, ":") {
		parts := strings.Split(basicAuth, ":")
		m.Use(auth.Basic(parts[0], parts[1]))
	}

	var static martini.Handler
	if appDir == "" {
		static = staticbin.Static("grafana-1.9.1", grafana.Asset)
	} else {
		static = martini.Static(appDir, martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
	}

	r.NotFound(static, http.NotFound)

	r.Get("/search", searchDashboards)
	r.Get("/dashboard/:id", getDashboard)
	r.Post("/dashboard/:id", saveDashboard)
	r.Delete("/dashboard/:id", deleteDashboard)
	r.Get("/plugins/datasource.gofana.js", gofanaDatasource)
	r.Get("/config.js", gofanaConfig)
	r.Get("/graphite/**", proxyGraphite)
	r.Post("/graphite/**", proxyGraphite)
	r.Get("/influxdb/**", proxyInfluxDB)
	r.Post("/influxdb/**", proxyInfluxDB)
	r.Get("/opentsdb/**", proxyOpenTSDB)
	r.Post("/opentsdb/**", proxyOpenTSDB)
	r.Get("/:provider/auth", authRedirect)
	r.Get("/:provider/oauth2callback", oauth2callback)
	r.Get("/signin", getSignin)

	// HTTP Listener
	wg.Add(1)
	go func() {
		defer wg.Done()
		log.Printf("HTTP listening on %s\n", httpAddr)
		if err := http.ListenAndServe(httpAddr, m); err != nil {
			log.Fatal(err)
		}
	}()

	// HTTPS Listener
	if sslCert != "" && sslKey != "" {
		wg.Add(1)
		go func() {
			defer wg.Done()
			log.Printf("HTTPS listening on %s", httpsAddr)
			if err := http.ListenAndServeTLS(httpsAddr, sslCert, sslKey, m); err != nil {
				log.Fatal(err)

			}
		}()
	}
	wg.Wait()
}
Ejemplo n.º 7
0
func main() {
	var serverPort int
	var localhost bool

	flag.IntVar(&serverPort, "port", 8056, "Port to listen on.")
	flag.BoolVar(&localhost, "localhost", false, "Listen on localhost only.")

	flag.Parse()

	var cardata []Record
	var carmutex sync.RWMutex

	m := martini.Classic()

	m.Use(gzip.All())
	m.Use(staticbin.Static("public", Asset))

	carfunc := func(res http.ResponseWriter, r *http.Request) {
		fmt.Println(time.Now())
		decoder := json.NewDecoder(r.Body)
		var rec Record

		err := decoder.Decode(&rec)

		if err != nil {
			log.Println(err)
		}

		recTime := time.Unix(0, 0)
		recTime = recTime.Add(time.Millisecond * time.Duration(rec.Timestamp))
		rec.DateTime = recTime
		fmt.Println(recTime)

		for rName, reading := range rec.Readings {
			if reading != "" && reading != "NO DATA" {
				segs := validValue.FindAllStringSubmatch(reading, -1)
				if len(segs) > 0 && len(segs[0]) > 2 {
					val := segs[0][1]
					//fmt.Println(rName, strings.TrimSpace(segs[0][1]), strings.TrimSpace(segs[0][2]))
					switch rName {
					case "BAROMETRIC_PRESSURE":
						rec.BarometricPressure = val
					case "INTAKE_MANIFOLD_PRESSURE":
						rec.IntakeManifoldPressure = val
					case "ENGINE_RPM":
						rec.EngineRPM = val
					case "ENGINE_COOLANT_TEMP":
						rec.EngineCoolantTemp = val
					case "AMBIENT_AIR_TEMP":
						rec.AmbientAirTemp = val
					case "SPEED":
						rec.Speed = val
					case "THROTTLE_POS":
						rec.ThrottlePos = val
					case "AIR_INTAKE_TEMP":
						rec.AirIntakeTemp = val
					}
				}
			}
		}

		fmt.Println(rec)

		carmutex.Lock()
		// Get latest time clear all trip data if the time we are
		// receiving is over an hour after the last time received.
		if len(cardata) > 0 {
			recentTime := cardata[len(cardata)-1].DateTime
			if rec.DateTime.Sub(recentTime) > time.Hour {
				cardata = []Record{}
			}
		}

		// Append received record to trip.
		cardata = append(cardata, rec)
		carmutex.Unlock()
	}

	m.Put("/", carfunc)
	m.Put("/data", carfunc)
	m.Put("/data/", carfunc)

	carview := func(w http.ResponseWriter, r *http.Request) {
		type DataSet struct {
			FieldName string
			RGBColor  string
			Values    []string
		}
		var chartData struct {
			RangeStart, RangeEnd time.Time
			Labels               []string
			DataSets             []DataSet
		}

		carmutex.RLock()
		chartData.DataSets = []DataSet{
			{FieldName: "Speed (km/h)", RGBColor: "220,220,220", Values: make([]string, len(cardata))},
			{FieldName: "Throttle (%)", RGBColor: "151,187,205", Values: make([]string, len(cardata))},
			{FieldName: "RPM (x100)", RGBColor: "70, 191, 189", Values: make([]string, len(cardata))},
		}
		for rIdx, rec := range cardata {
			if chartData.RangeStart.IsZero() {
				chartData.RangeStart = rec.DateTime
			}
			chartData.RangeEnd = rec.DateTime
			chartData.Labels = append(chartData.Labels, rec.DateTime.Format("15:04:05"))
			chartData.DataSets[0].Values[rIdx] = rec.Speed
			chartData.DataSets[1].Values[rIdx] = rec.ThrottlePos
			rpm, _ := strconv.ParseInt(rec.EngineRPM, 10, 64)
			chartData.DataSets[2].Values[rIdx] = fmt.Sprint(rpm / 100)
		}
		carmutex.RUnlock()

		t, err := parseAssets("templates/template.linechart.html", "templates/template.nav.html")
		if err != nil {
			http.Error(w, err.Error(), 500)
			return
		}
		err = t.Execute(w, chartData)
		if err != nil {
			http.Error(w, err.Error(), 500)
		}
	}

	m.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/carview", http.StatusFound)
	})
	m.Get("/carview", carview)

	fmt.Println("Listening on port", serverPort)
	listenAddress := ""
	if localhost {
		listenAddress = fmt.Sprintf("127.0.0.1:%d", serverPort)
	} else {
		listenAddress = fmt.Sprintf(":%d", serverPort)
	}
	http.ListenAndServe(listenAddress, m)
}
Ejemplo n.º 8
0
//NewServer returns new GohanAPIServer
func NewServer(configFile string) (*Server, error) {
	manager := schema.GetManager()
	config := util.GetConfig()
	err := config.ReadConfig(configFile)
	err = os.Chdir(path.Dir(configFile))
	if err != nil {
		return nil, fmt.Errorf("Config load error: %s", err)
	}
	err = l.SetUpLogging(config)
	if err != nil {
		return nil, fmt.Errorf("Logging setup error: %s", err)
	}
	log.Info("logging initialized")

	server := &Server{}

	m := martini.Classic()
	m.Handlers()
	m.Use(middleware.Logging())
	m.Use(martini.Recovery())
	m.Use(middleware.JSONURLs())
	m.Use(middleware.WithContext())

	server.martini = m

	port := os.Getenv("PORT")

	if port == "" {
		port = "9091"
	}

	setupEditor(server)

	server.timelimit = config.GetInt("extension/timelimit", 30)
	server.extensions = config.GetStringList("extension/use", []string{
		"javascript",
		"gohanscript",
		"go",
	})
	schema.DefaultExtension = config.GetString("extension/default", "javascript")
	server.address = config.GetString("address", ":"+port)
	if config.GetBool("tls/enabled", false) {
		log.Info("TLS enabled")
		server.tls = &tlsConfig{
			KeyFile:  config.GetString("tls/key_file", "./etc/key.pem"),
			CertFile: config.GetString("tls/cert_file", "./etc/cert.pem"),
		}
	}

	etcdServers := config.GetStringList("etcd", nil)
	if etcdServers != nil {
		log.Info("etcd servers: %s", etcdServers)
		server.sync = etcd.NewSync(etcdServers)
	}

	server.connectDB()

	schemaFiles := config.GetStringList("schemas", nil)
	if schemaFiles == nil {
		log.Fatal("No schema specified in configuraion")
	} else {
		err = manager.LoadSchemasFromFiles(schemaFiles...)
		if err != nil {
			return nil, fmt.Errorf("invalid schema: %s", err)
		}
	}
	if !config.GetBool("database/no_init", false) {
		server.initDB()
	}

	if config.GetList("database/initial_data", nil) != nil {
		initialDataList := config.GetList("database/initial_data", nil)
		for _, initialData := range initialDataList {
			initialDataConfig := initialData.(map[string]interface{})
			inType := initialDataConfig["type"].(string)
			inConnection := initialDataConfig["connection"].(string)
			log.Info("Importing data from %s ...", inConnection)
			inDB, err := db.ConnectDB(inType, inConnection, db.DefaultMaxOpenConn)
			if err != nil {
				log.Fatal(err)
			}
			db.CopyDBResources(inDB, server.db, false)
		}
	}

	if config.GetBool("keystone/use_keystone", false) {
		//TODO remove this
		if config.GetBool("keystone/fake", false) {
			server.keystoneIdentity = &middleware.FakeIdentity{}
			//TODO(marcin) requests to fake server also get authenticated
			//             we need a separate routing Group
			log.Info("Debug Mode with Fake Keystone Server")
		} else {
			log.Info("Keystone backend server configured")
			server.keystoneIdentity, err = cloud.NewKeystoneIdentity(
				config.GetString("keystone/auth_url", "http://localhost:35357/v3"),
				config.GetString("keystone/user_name", "admin"),
				config.GetString("keystone/password", "password"),
				config.GetString("keystone/domain_name", "Default"),
				config.GetString("keystone/tenant_name", "admin"),
				config.GetString("keystone/version", ""),
			)
			if err != nil {
				log.Fatal(err)
			}
		}
		m.MapTo(server.keystoneIdentity, (*middleware.IdentityService)(nil))
		m.Use(middleware.Authentication())
		//m.Use(Authorization())
	} else {
		m.MapTo(&middleware.NoIdentityService{}, (*middleware.IdentityService)(nil))
		m.Map(schema.NewAuthorization("admin", "admin", "admin_token", []string{"admin"}, nil))
	}

	if err != nil {
		return nil, fmt.Errorf("invalid base dir: %s", err)
	}

	server.addOptionsRoute()
	cors := config.GetString("cors", "")
	if cors != "" {
		log.Info("Enabling CORS for %s", cors)
		if cors == "*" {
			log.Warning("cors for * have security issue")
		}
		server.martini.Use(func(rw http.ResponseWriter, r *http.Request) {
			rw.Header().Add("Access-Control-Allow-Origin", cors)
			rw.Header().Add("Access-Control-Allow-Headers", "X-Auth-Token, Content-Type")
			rw.Header().Add("Access-Control-Expose-Headers", "X-Total-Count")
			rw.Header().Add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE")
		})
	}

	documentRoot := config.GetString("document_root", "embed")
	if config.GetBool("webui_config/enabled", false) {
		m.Use(func(res http.ResponseWriter, req *http.Request, c martini.Context) {
			if req.URL.Path != "/webui/config.json" {
				c.Next()
				return
			}
			address := config.GetString("webui_config/address", server.address)
			if address[0] == ':' {
				address = "__HOST__" + address
			}
			baseURL := "http://" + address
			authURL := "http://" + address + "/v2.0"
			if config.GetBool("webui_config/tls", config.GetBool("tls/enabled", false)) {
				baseURL = "https://" + address
				authURL = "https://" + address + "/v2.0"
			}
			authURL = config.GetString("webui_config/auth_url", authURL)
			webUIConfig := map[string]interface{}{
				"authUrl": authURL,
				"gohan": map[string]interface{}{
					"schema": "/gohan/v0.1/schemas",
					"url":    baseURL,
				},
			}
			routes.ServeJson(res, webUIConfig)
		})
	}
	if documentRoot == "embed" {
		m.Use(staticbin.Static("public", util.Asset, staticbin.Options{
			SkipLogging: true,
		}))
	} else {
		log.Info("Static file serving from %s", documentRoot)
		documentRootABS, err := filepath.Abs(documentRoot)
		if err != nil {
			return nil, err
		}
		server.martini.Use(martini.Static(documentRootABS, martini.StaticOptions{
			SkipLogging: true,
		}))
	}
	server.mapRoutes()

	maxWorkerCount := config.GetInt("workers", 100)
	server.queue = job.NewQueue(uint(maxWorkerCount))

	return server, nil
}
Ejemplo n.º 9
0
// main executes a webserver.
func main() {
	var m = martini.Classic()
	m.Use(render.Renderer())
	if serveAssetsFromFs != "" {
		log.Debugf("Dev mode: serving webapp from %s", assetFsPath)
		m.Use(martini.Static(assetFsPath))
		m.Use(cors.Allow(&cors.Options{
			AllowOrigins:     []string{"http://localhost:9090"},
			AllowMethods:     []string{"PUT", "GET", "POST"},
			AllowHeaders:     []string{"Origin", "Content-Type"},
			ExposeHeaders:    []string{"Content-Length"},
			AllowCredentials: true,
		}))
	} else {
		log.Debugf("Production mode: serving webapp from the binary")
		m.Use(staticbin.Static(assetFsPath, Asset))
	}

	//reverse proxy to Zeppelin-container
	zeppelin := newZeppelinProxy()
	m.Get("/zeppelin**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Post("/zeppelin**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Delete("/zeppelin**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})

	m.Get("/assets/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Get("/styles/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Get("/scripts/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Get("/components/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Get("/app/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})
	m.Get("/fonts/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})

	//Websocket proxy
	websocketRP := newWebsocketProxy()
	m.Get("/ws**", func(w http.ResponseWriter, r *http.Request) {
		websocketRP.ServeHTTP(w, r)
	})

	//Cluster API - reverse proxy for Spark Master
	sparkMaster := newSparkMasterProxy()
	m.Get("/api/v1/cluster", func(w http.ResponseWriter, r *http.Request) {
		sparkMaster.ServeHTTP(w, r)
	})

	//Auth API
	m.Group("/api/v1/users", func(r martini.Router) {
		r.Put("/login", func(w http.ResponseWriter, r *http.Request) {
			loginService.Login(w, r)
		})

		r.Post("/logout", func(w http.ResponseWriter, r *http.Request) {
			loginService.Logout(w, r)
		})

		r.Get("/whoiam", func(w http.ResponseWriter, r *http.Request) {
			loginService.Whoami(w, r)
		})
	})

	//Containers API
	m.Map(&Docker{})
	m.Group("/api/v1/containers", func(r martini.Router) {
		r.Post("/list", binding.Bind(ListContainersReq{}), ListContainers)

		//IN: 'user-memory-cpu'
		r.Post("/create", binding.Bind(CreateContainerReq{}), CreateContainer)

		//IN: containerId
		r.Post("/delete", binding.Bind(DeleteContainerReq{}), DeleteContainer)

		r.Get("/images", func(r render.Render, docker *Docker) {
			r.JSON(200, docker.ListImages())
		})
	})

	m.Get("/**", func(w http.ResponseWriter, r *http.Request) {
		zeppelin.ServeHTTP(w, r)
	})

	go startAutoupdate()
	go func() { //debug output
		for {
			log.Debugf("Running program version: %v", internalVersion)
			time.Sleep(versionPrintInterval)
		}
	}()
	m.Run()
}