Пример #1
0
func APIHandler(conf *Config) http.Handler {
	api := &API{
		conf: conf,
	}
	if conf.Cache {
		if err := api.cacheDashboardJS(); err != nil {
			panic(err)
		}
	}

	router := httprouter.New()
	router2 := httprouter.New()

	prefixPath := func(p string) string {
		return path.Join(conf.PathPrefix, p)
	}

	router.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	router.POST(prefixPath("/user/sessions"), api.WrapHandler(api.Login))
	router.DELETE(prefixPath("/user/session"), api.WrapHandler(api.Logout))

	router.GET(prefixPath("/config"), api.WrapHandler(api.GetConfig))
	router.GET(prefixPath("/cert"), api.WrapHandler(api.GetCert))

	router.NotFound = router2.ServeHTTP
	router2.GET(prefixPath("/*path"), api.WrapHandler(api.ServeAsset))

	return httphelper.ContextInjector("dashboard",
		httphelper.NewRequestLogger(
			api.CorsHandler(router)))
}
Пример #2
0
// NewHandler returns a new instance of Handler.
func NewHandler() *Handler {
	h := &Handler{router: httprouter.New()}

	h.router.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	h.router.PUT("/services/:service", h.servePutService)
	h.router.DELETE("/services/:service", h.serveDeleteService)
	h.router.GET("/services/:service", h.serveGetService)

	h.router.PUT("/services/:service/meta", h.servePutServiceMeta)
	h.router.GET("/services/:service/meta", h.serveGetServiceMeta)

	h.router.PUT("/services/:service/instances/:instance_id", h.servePutInstance)
	h.router.DELETE("/services/:service/instances/:instance_id", h.serveDeleteInstance)
	h.router.GET("/services/:service/instances", h.serveGetInstances)

	h.router.PUT("/services/:service/leader", h.servePutLeader)
	h.router.GET("/services/:service/leader", h.serveGetLeader)

	h.router.GET("/raft/leader", h.serveGetRaftLeader)
	h.router.POST("/raft/nodes", h.servePostRaftNodes)
	h.router.DELETE("/raft/nodes", h.serveDeleteRaftNodes)

	h.router.GET("/ping", h.servePing)

	return h
}
Пример #3
0
func main() {
	defer shutdown.Exit()

	dsn := &mariadb.DSN{
		Host:     serviceHost + ":3306",
		User:     "******",
		Password: os.Getenv("MYSQL_PWD"),
		Database: "mysql",
	}
	db, err := sql.Open("mysql", dsn.String())
	api := &API{db}

	router := httprouter.New()
	router.POST("/databases", httphelper.WrapHandler(api.createDatabase))
	router.DELETE("/databases", httphelper.WrapHandler(api.dropDatabase))
	router.GET("/ping", httphelper.WrapHandler(api.ping))

	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	addr := ":" + port

	hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr)
	if err != nil {
		shutdown.Fatal(err)
	}
	shutdown.BeforeExit(func() { hb.Close() })

	handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router))
	shutdown.Fatal(http.ListenAndServe(addr, handler))
}
Пример #4
0
func main() {
	defer shutdown.Exit()

	db := postgres.Wait(&postgres.Conf{
		Service:  serviceName,
		User:     "******",
		Password: os.Getenv("PGPASSWORD"),
		Database: "postgres",
	}, nil)
	api := &pgAPI{db}

	router := httprouter.New()
	router.POST("/databases", api.createDatabase)
	router.DELETE("/databases", api.dropDatabase)
	router.GET("/ping", api.ping)

	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	addr := ":" + port

	hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr)
	if err != nil {
		shutdown.Fatal(err)
	}
	shutdown.BeforeExit(func() { hb.Close() })

	handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router))
	shutdown.Fatal(http.ListenAndServe(addr, handler))
}
Пример #5
0
func main() {
	defer shutdown.Exit()

	api := &API{}

	router := httprouter.New()
	router.POST("/databases", httphelper.WrapHandler(api.createDatabase))
	router.DELETE("/databases", httphelper.WrapHandler(api.dropDatabase))
	router.GET("/ping", httphelper.WrapHandler(api.ping))

	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	addr := ":" + port

	hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr)
	if err != nil {
		shutdown.Fatal(err)
	}
	shutdown.BeforeExit(func() { hb.Close() })

	handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router))
	shutdown.Fatal(http.ListenAndServe(addr, handler))
}
Пример #6
0
func ServeHTTP() error {
	api := &httpAPI{
		InstallerPrompts: make(map[string]*httpPrompt),
		InstallerStacks:  make(map[string]*httpInstaller),
	}

	if creds, err := aws.EnvCreds(); err == nil {
		api.AWSEnvCreds = creds
	}

	httpRouter := httprouter.New()

	httpRouter.GET("/", api.ServeTemplate)
	httpRouter.GET("/install", api.ServeTemplate)
	httpRouter.GET("/install/:id", api.ServeTemplate)
	httpRouter.POST("/install", api.InstallHandler)
	httpRouter.GET("/events/:id", api.EventsHandler)
	httpRouter.POST("/prompt/:id", api.PromptHandler)
	httpRouter.GET("/assets/*assetPath", api.ServeAsset)

	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return err
	}
	addr := fmt.Sprintf("http://localhost:%d", l.Addr().(*net.TCPAddr).Port)
	if err := api.OpenAddr(addr); err != nil {
		fmt.Printf("Open %s in your browser to continue.\n", addr)
	}
	return http.Serve(l, api.CorsHandler(httpRouter, addr))
}
Пример #7
0
func ServeHTTP() error {
	logger := log.New()
	installer := NewInstaller(logger)

	api := &httpAPI{
		Installer: installer,
		logger:    logger,
		clientConfig: installerJSConfig{
			Endpoints: map[string]string{
				"clusters":           "/clusters",
				"cluster":            "/clusters/:id",
				"upload_backup":      "/clusters/:id/upload-backup",
				"cert":               "/clusters/:id/ca-cert",
				"events":             "/events",
				"prompt":             "/clusters/:id/prompts/:prompt_id",
				"credentials":        "/credentials",
				"regions":            "/regions",
				"azureSubscriptions": "/azure/subscriptions",
			},
		},
	}

	if creds, err := aws.EnvCreds(); err == nil {
		api.AWSEnvCreds = creds
		if c, err := creds.Credentials(); err == nil {
			api.clientConfig.HasAWSEnvCredentials = true
			api.clientConfig.AWSEnvCredentialsID = c.AccessKeyID
		}
	}

	httpRouter := httprouter.New()

	httpRouter.GET("/", api.ServeTemplate)
	httpRouter.GET("/credentials", api.ServeTemplate)
	httpRouter.GET("/credentials/:id", api.ServeTemplate)
	httpRouter.GET("/clusters/:id", api.ServeTemplate)
	httpRouter.POST("/clusters/:id/upload-backup", api.ReceiveBackup)
	httpRouter.GET("/clusters/:id/ca-cert", api.GetCert)
	httpRouter.GET("/clusters/:id/delete", api.ServeTemplate)
	httpRouter.GET("/oauth/azure", api.ServeTemplate)
	httpRouter.DELETE("/clusters/:id", api.DeleteCluster)
	httpRouter.GET("/clusters", api.RedirectRoot)
	httpRouter.POST("/clusters", api.LaunchCluster)
	httpRouter.GET("/events", api.Events)
	httpRouter.POST("/clusters/:id/prompts/:prompt_id", api.Prompt)
	httpRouter.GET("/assets/*assetPath", api.ServeAsset)
	httpRouter.POST("/credentials", api.NewCredential)
	httpRouter.DELETE("/credentials/:type/:id", api.DeleteCredential)
	httpRouter.GET("/regions", api.GetCloudRegions)
	httpRouter.GET("/azure/subscriptions", api.GetAzureSubscriptions)

	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return err
	}
	addr := fmt.Sprintf("http://localhost:%d", l.Addr().(*net.TCPAddr).Port)
	fmt.Printf("Open %s in your browser to continue.\n", addr)
	browser.OpenURL(addr)
	return http.Serve(l, api.CorsHandler(httpRouter, addr))
}
Пример #8
0
func NewHTTPHandler(ds Datastore) http.Handler {
	router := httprouter.New()

	api := &httpAPI{
		Store: ds,
	}

	router.PUT("/services/:service", api.AddService)
	router.DELETE("/services/:service", api.RemoveService)
	router.GET("/services/:service", api.GetServiceStream)

	router.PUT("/services/:service/meta", api.SetServiceMeta)
	router.GET("/services/:service/meta", api.GetServiceMeta)

	router.PUT("/services/:service/instances/:instance_id", api.AddInstance)
	router.DELETE("/services/:service/instances/:instance_id", api.RemoveInstance)
	router.GET("/services/:service/instances", api.GetInstances)

	router.PUT("/services/:service/leader", api.SetLeader)
	router.GET("/services/:service/leader", api.GetLeader)

	router.GET("/ping", func(http.ResponseWriter, *http.Request, httprouter.Params) {})

	return router
}
Пример #9
0
// NewHandler returns a new instance of Handler.
func NewHandler() *Handler {
	r := httprouter.New()
	h := &Handler{Handler: r}

	if os.Getenv("DEBUG") != "" {
		h.Handler = hh.ContextInjector("discoverd", hh.NewRequestLogger(h.Handler))
	}

	r.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	r.PUT("/services/:service", h.servePutService)
	r.DELETE("/services/:service", h.serveDeleteService)
	r.GET("/services/:service", h.serveGetService)

	r.PUT("/services/:service/meta", h.servePutServiceMeta)
	r.GET("/services/:service/meta", h.serveGetServiceMeta)

	r.PUT("/services/:service/instances/:instance_id", h.servePutInstance)
	r.DELETE("/services/:service/instances/:instance_id", h.serveDeleteInstance)
	r.GET("/services/:service/instances", h.serveGetInstances)

	r.PUT("/services/:service/leader", h.servePutLeader)
	r.GET("/services/:service/leader", h.serveGetLeader)

	r.GET("/raft/leader", h.serveGetRaftLeader)
	r.POST("/raft/nodes", h.servePostRaftNodes)
	r.DELETE("/raft/nodes", h.serveDeleteRaftNodes)

	r.GET("/ping", h.servePing)

	return h
}
Пример #10
0
// NewHandler returns a new instance of Handler.
func NewHandler() *Handler {
	h := &Handler{
		router: httprouter.New(),
	}
	h.router.Handler("GET", status.Path, status.Handler(h.healthStatus))
	h.router.GET("/status", h.handleGetStatus)
	h.router.POST("/stop", h.handlePostStop)
	return h
}
Пример #11
0
func apiHandler(agg *Aggregator) http.Handler {
	api := aggregatorAPI{agg: agg}
	r := httprouter.New()

	r.GET("/log/:channel_id", httphelper.WrapHandler(api.GetLog))
	return httphelper.ContextInjector(
		"logaggregator-api",
		httphelper.NewRequestLogger(r),
	)
}
Пример #12
0
// NewAPIHandler returns a new instance of APIHandler.
func NewHandler() *Handler {
	h := &Handler{
		router: httprouter.New(),
		Logger: log15.New(),
	}
	h.router.POST("/clusters", h.servePostCluster)
	h.router.DELETE("/clusters", h.serveDeleteCluster)
	h.router.GET("/ping", h.serveGetPing)
	return h
}
Пример #13
0
func apiHandler(agg *Aggregator, cursors *HostCursors) http.Handler {
	api := aggregatorAPI{agg, cursors}
	r := httprouter.New()

	r.Handler("GET", status.Path, status.HealthyHandler)
	r.GET("/log/:channel_id", httphelper.WrapHandler(api.GetLog))
	r.GET("/cursors", httphelper.WrapHandler(api.GetCursors))
	return httphelper.ContextInjector(
		"logaggregator-api",
		httphelper.NewRequestLogger(r),
	)
}
Пример #14
0
func (h *Host) ServeHTTP() {
	r := httprouter.New()

	r.POST("/attach", (&attachHandler{state: h.state, backend: h.backend}).ServeHTTP)

	jobAPI := &jobAPI{host: h}
	jobAPI.RegisterRoutes(r)

	volAPI := volumeapi.NewHTTPAPI(cluster.NewClient(), h.vman)
	volAPI.RegisterRoutes(r)

	go http.Serve(h.listener, httphelper.ContextInjector("host", httphelper.NewRequestLogger(r)))
}
Пример #15
0
func ServeHTTP(pg *Postgres, peer *state.Peer, hb discoverd.Heartbeater, log log15.Logger) error {
	api := &HTTP{
		pg:   pg,
		peer: peer,
		hb:   hb,
		log:  log,
	}
	r := httprouter.New()
	r.Handler("GET", status.Path, status.Handler(api.GetHealthStatus))
	r.GET("/status", api.GetStatus)
	r.POST("/stop", api.Stop)
	return http.ListenAndServe(":5433", r)
}
Пример #16
0
func (h *Host) ServeHTTP() {
	r := httprouter.New()

	r.POST("/attach", newAttachHandler(h.state, h.backend, h.log).ServeHTTP)

	jobAPI := &jobAPI{
		host: h,
		addJobRatelimitBucket: make(chan struct{}, h.maxJobConcurrency),
	}
	jobAPI.RegisterRoutes(r)

	volAPI := volumeapi.NewHTTPAPI(cluster.NewClient(), h.vman)
	volAPI.RegisterRoutes(r)

	go http.Serve(h.listener, httphelper.ContextInjector("host", httphelper.NewRequestLogger(r)))
}
Пример #17
0
func apiHandler(rtr *Router) http.Handler {
	api := &API{router: rtr}
	r := httprouter.New()

	r.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	r.POST("/routes", httphelper.WrapHandler(api.CreateRoute))
	r.PUT("/routes/:route_type/:id", httphelper.WrapHandler(api.UpdateRoute))
	r.GET("/routes", httphelper.WrapHandler(api.GetRoutes))
	r.GET("/routes/:route_type/:id", httphelper.WrapHandler(api.GetRoute))
	r.DELETE("/routes/:route_type/:id", httphelper.WrapHandler(api.DeleteRoute))
	r.GET("/events", httphelper.WrapHandler(api.StreamEvents))

	r.HandlerFunc("GET", "/debug/*path", pprof.Handler.ServeHTTP)

	return httphelper.ContextInjector("router", httphelper.NewRequestLogger(r))
}
Пример #18
0
// NewHandler returns a new instance of Handler.
func NewHandler(proxy bool, peers []string) *Handler {
	r := httprouter.New()

	h := &Handler{Handler: r}
	h.Shutdown.Store(false)

	h.Peers = peers
	h.Proxy.Store(proxy)

	if os.Getenv("DEBUG") != "" {
		h.Handler = hh.ContextInjector("discoverd", hh.NewRequestLogger(h.Handler))
	}

	r.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	r.PUT("/services/:service", h.servePutService)
	r.DELETE("/services/:service", h.serveDeleteService)
	r.GET("/services/:service", h.serveGetService)

	r.PUT("/services/:service/meta", h.servePutServiceMeta)
	r.GET("/services/:service/meta", h.serveGetServiceMeta)

	r.PUT("/services/:service/instances/:instance_id", h.servePutInstance)
	r.DELETE("/services/:service/instances/:instance_id", h.serveDeleteInstance)
	r.GET("/services/:service/instances", h.serveGetInstances)

	r.PUT("/services/:service/leader", h.servePutLeader)
	r.GET("/services/:service/leader", h.serveGetLeader)

	r.GET("/raft/leader", h.serveGetRaftLeader)
	r.GET("/raft/peers", h.serveGetRaftPeers)
	r.PUT("/raft/peers/:peer", h.servePutRaftPeer)
	r.DELETE("/raft/peers/:peer", h.serveDeleteRaftPeer)
	r.POST("/raft/promote", h.servePromote)
	r.POST("/raft/demote", h.serveDemote)

	r.GET("/ping", h.servePing)

	r.POST("/shutdown", h.serveShutdown)
	return h
}
Пример #19
0
func serveHTTP(h *Host, addr string, attach *attachHandler, clus *cluster.Client, vman *volumemanager.Manager, connectDiscoverd func(string) error) error {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	shutdown.BeforeExit(func() { l.Close() })

	r := httprouter.New()

	r.POST("/attach", attach.ServeHTTP)

	jobAPI := &jobAPI{
		host:             h,
		connectDiscoverd: connectDiscoverd,
	}
	jobAPI.RegisterRoutes(r)
	volAPI := volumeapi.NewHTTPAPI(clus, vman)
	volAPI.RegisterRoutes(r)

	go http.Serve(l, httphelper.ContextInjector("host", httphelper.NewRequestLogger(r)))

	return nil
}
Пример #20
0
func (r *Runner) start() error {
	r.authKey = os.Getenv("AUTH_KEY")
	if r.authKey == "" {
		return errors.New("AUTH_KEY not set")
	}

	r.githubToken = os.Getenv("GITHUB_TOKEN")
	if r.githubToken == "" {
		return errors.New("GITHUB_TOKEN not set")
	}

	awsAuth, err := aws.EnvAuth()
	if err != nil {
		return err
	}
	r.s3Bucket = s3.New(awsAuth, aws.USEast).Bucket(logBucket)

	_, listenPort, err = net.SplitHostPort(args.ListenAddr)
	if err != nil {
		return err
	}

	bc := r.bc
	bc.Network = r.allocateNet()
	if r.rootFS, err = cluster.BuildFlynn(bc, args.RootFS, "origin/master", false, os.Stdout); err != nil {
		return fmt.Errorf("could not build flynn: %s", err)
	}
	r.releaseNet(bc.Network)
	shutdown.BeforeExit(func() { removeRootFS(r.rootFS) })

	db, err := bolt.Open(args.DBPath, 0600, &bolt.Options{Timeout: 5 * time.Second})
	if err != nil {
		return fmt.Errorf("could not open db: %s", err)
	}
	r.db = db
	shutdown.BeforeExit(func() { r.db.Close() })

	if err := r.db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists(dbBucket)
		return err
	}); err != nil {
		return fmt.Errorf("could not create builds bucket: %s", err)
	}

	for i := 0; i < maxConcurrentBuilds; i++ {
		r.buildCh <- struct{}{}
	}

	if err := r.buildPending(); err != nil {
		log.Printf("could not build pending builds: %s", err)
	}

	go r.connectIRC()
	go r.watchEvents()

	router := httprouter.New()
	router.RedirectTrailingSlash = true
	router.Handler("GET", "/", http.RedirectHandler("/builds", 302))
	router.POST("/", r.handleEvent)
	router.GET("/builds/:build", r.getBuildLog)
	router.POST("/builds/:build/restart", r.restartBuild)
	router.POST("/builds/:build/explain", r.explainBuild)
	router.GET("/builds", r.getBuilds)
	router.ServeFiles("/assets/*filepath", http.Dir(args.AssetsDir))
	router.GET("/cluster/:cluster", r.clusterAPI(r.getCluster))
	router.POST("/cluster/:cluster", r.clusterAPI(r.addHost))
	router.POST("/cluster/:cluster/release", r.clusterAPI(r.addReleaseHosts))
	router.DELETE("/cluster/:cluster/:host", r.clusterAPI(r.removeHost))

	srv := &http.Server{
		Addr:      args.ListenAddr,
		Handler:   router,
		TLSConfig: tlsconfig.SecureCiphers(nil),
	}
	log.Println("Listening on", args.ListenAddr, "...")
	if err := srv.ListenAndServeTLS(args.TLSCert, args.TLSKey); err != nil {
		return fmt.Errorf("ListenAndServeTLS: %s", err)
	}

	return nil
}
Пример #21
0
func appHandler(c handlerConfig) http.Handler {
	err := schema.Load(schemaRoot)
	if err != nil {
		shutdown.Fatal(err)
	}

	q := que.NewClient(c.pgxpool)
	providerRepo := NewProviderRepo(c.db)
	keyRepo := NewKeyRepo(c.db)
	resourceRepo := NewResourceRepo(c.db)
	appRepo := NewAppRepo(c.db, os.Getenv("DEFAULT_ROUTE_DOMAIN"), c.rc)
	artifactRepo := NewArtifactRepo(c.db)
	releaseRepo := NewReleaseRepo(c.db)
	jobRepo := NewJobRepo(c.db)
	formationRepo := NewFormationRepo(c.db, appRepo, releaseRepo, artifactRepo)
	deploymentRepo := NewDeploymentRepo(c.db, c.pgxpool)

	api := controllerAPI{
		appRepo:        appRepo,
		releaseRepo:    releaseRepo,
		providerRepo:   providerRepo,
		formationRepo:  formationRepo,
		artifactRepo:   artifactRepo,
		jobRepo:        jobRepo,
		resourceRepo:   resourceRepo,
		deploymentRepo: deploymentRepo,
		clusterClient:  c.cc,
		logaggc:        c.lc,
		routerc:        c.rc,
		que:            q,
	}

	httpRouter := httprouter.New()

	crud(httpRouter, "apps", ct.App{}, appRepo)
	crud(httpRouter, "releases", ct.Release{}, releaseRepo)
	crud(httpRouter, "providers", ct.Provider{}, providerRepo)
	crud(httpRouter, "artifacts", ct.Artifact{}, artifactRepo)
	crud(httpRouter, "keys", ct.Key{}, keyRepo)

	httpRouter.POST("/apps/:apps_id", httphelper.WrapHandler(api.UpdateApp))
	httpRouter.GET("/apps/:apps_id/log", httphelper.WrapHandler(api.appLookup(api.AppLog)))
	httpRouter.GET("/apps/:apps_id/events", httphelper.WrapHandler(api.appLookup(api.AppEvents)))
	httpRouter.DELETE("/apps/:apps_id", httphelper.WrapHandler(api.appLookup(api.DeleteApp)))

	httpRouter.PUT("/apps/:apps_id/formations/:releases_id", httphelper.WrapHandler(api.appLookup(api.PutFormation)))
	httpRouter.GET("/apps/:apps_id/formations/:releases_id", httphelper.WrapHandler(api.appLookup(api.GetFormation)))
	httpRouter.DELETE("/apps/:apps_id/formations/:releases_id", httphelper.WrapHandler(api.appLookup(api.DeleteFormation)))
	httpRouter.GET("/apps/:apps_id/formations", httphelper.WrapHandler(api.appLookup(api.ListFormations)))
	httpRouter.GET("/formations", httphelper.WrapHandler(api.GetFormations))

	httpRouter.POST("/apps/:apps_id/jobs", httphelper.WrapHandler(api.appLookup(api.RunJob)))
	httpRouter.GET("/apps/:apps_id/jobs/:jobs_id", httphelper.WrapHandler(api.appLookup(api.GetJob)))
	httpRouter.PUT("/apps/:apps_id/jobs/:jobs_id", httphelper.WrapHandler(api.appLookup(api.PutJob)))
	httpRouter.GET("/apps/:apps_id/jobs", httphelper.WrapHandler(api.appLookup(api.ListJobs)))
	httpRouter.DELETE("/apps/:apps_id/jobs/:jobs_id", httphelper.WrapHandler(api.appLookup(api.KillJob)))

	httpRouter.POST("/apps/:apps_id/deploy", httphelper.WrapHandler(api.appLookup(api.CreateDeployment)))
	httpRouter.GET("/deployments/:deployment_id", httphelper.WrapHandler(api.GetDeployment))

	httpRouter.PUT("/apps/:apps_id/release", httphelper.WrapHandler(api.appLookup(api.SetAppRelease)))
	httpRouter.GET("/apps/:apps_id/release", httphelper.WrapHandler(api.appLookup(api.GetAppRelease)))
	httpRouter.GET("/apps/:apps_id/releases", httphelper.WrapHandler(api.appLookup(api.GetAppReleases)))

	httpRouter.POST("/providers/:providers_id/resources", httphelper.WrapHandler(api.ProvisionResource))
	httpRouter.GET("/providers/:providers_id/resources", httphelper.WrapHandler(api.GetProviderResources))
	httpRouter.GET("/providers/:providers_id/resources/:resources_id", httphelper.WrapHandler(api.GetResource))
	httpRouter.PUT("/providers/:providers_id/resources/:resources_id", httphelper.WrapHandler(api.PutResource))
	httpRouter.DELETE("/providers/:providers_id/resources/:resources_id", httphelper.WrapHandler(api.DeleteResource))
	httpRouter.GET("/apps/:apps_id/resources", httphelper.WrapHandler(api.appLookup(api.GetAppResources)))

	httpRouter.POST("/apps/:apps_id/routes", httphelper.WrapHandler(api.appLookup(api.CreateRoute)))
	httpRouter.GET("/apps/:apps_id/routes", httphelper.WrapHandler(api.appLookup(api.GetRouteList)))
	httpRouter.GET("/apps/:apps_id/routes/:routes_type/:routes_id", httphelper.WrapHandler(api.appLookup(api.GetRoute)))
	httpRouter.DELETE("/apps/:apps_id/routes/:routes_type/:routes_id", httphelper.WrapHandler(api.appLookup(api.DeleteRoute)))

	httpRouter.POST("/apps/:apps_id/meta", httphelper.WrapHandler(api.appLookup(api.UpdateAppMeta)))

	return httphelper.ContextInjector("controller",
		httphelper.NewRequestLogger(muxHandler(httpRouter, c.keys)))
}