func registerHandlers(enableProfiling bool, port int, ic *GenericController) { mux := http.NewServeMux() // expose health check endpoint (/healthz) healthz.InstallHandler(mux, healthz.PingHealthz, ic.cfg.Backend, ) mux.Handle("/metrics", promhttp.Handler()) mux.HandleFunc("/build", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) b, _ := json.Marshal(ic.Info()) w.Write(b) }) mux.HandleFunc("/stop", func(w http.ResponseWriter, r *http.Request) { syscall.Kill(syscall.Getpid(), syscall.SIGTERM) }) if enableProfiling { mux.HandleFunc("/debug/pprof/", pprof.Index) mux.HandleFunc("/debug/pprof/profile", pprof.Profile) mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) mux.HandleFunc("/debug/pprof/trace", pprof.Trace) } server := &http.Server{ Addr: fmt.Sprintf(":%v", port), Handler: mux, } glog.Fatal(server.ListenAndServe()) }
// MakeHTTPHandler mounts the endpoints into a REST-y HTTP handler. func MakeHTTPHandler(ctx context.Context, e Endpoints, imagePath string, logger log.Logger) http.Handler { r := mux.NewRouter().StrictSlash(false) options := []httptransport.ServerOption{ httptransport.ServerErrorLogger(logger), httptransport.ServerErrorEncoder(encodeError), } // GET /catalogue List // GET /catalogue/size Count // GET /catalogue/{id} Get // GET /tags Tags // GET /health Health Check r.Methods("GET").Path("/catalogue").Handler(httptransport.NewServer( ctx, e.ListEndpoint, decodeListRequest, encodeListResponse, options..., )) r.Methods("GET").Path("/catalogue/size").Handler(httptransport.NewServer( ctx, e.CountEndpoint, decodeCountRequest, encodeResponse, options..., )) r.Methods("GET").Path("/catalogue/{id}").Handler(httptransport.NewServer( ctx, e.GetEndpoint, decodeGetRequest, encodeGetResponse, // special case, this one can have an error options..., )) r.Methods("GET").Path("/tags").Handler(httptransport.NewServer( ctx, e.TagsEndpoint, decodeTagsRequest, encodeResponse, options..., )) r.Methods("GET").PathPrefix("/catalogue/images/").Handler(http.StripPrefix( "/catalogue/images/", http.FileServer(http.Dir(imagePath)), )) r.Methods("GET").PathPrefix("/health").Handler(httptransport.NewServer( ctx, e.HealthEndpoint, decodeHealthRequest, encodeHealthResponse, options..., )) r.Handle("/metrics", promhttp.Handler()) return r }
// DebugServer starts a server to receive debug information. Typical // usage is to start it in a goroutine, configured with an address // from the appropriate configuration object: // // go cmd.DebugServer(c.XA.DebugAddr) func DebugServer(addr string) { m := expvar.NewMap("enabled-features") features.Export(m) if addr == "" { log.Fatalf("unable to boot debug server because no address was given for it. Set debugAddr.") } ln, err := net.Listen("tcp", addr) if err != nil { log.Fatalf("unable to boot debug server on %#v", addr) } http.Handle("/metrics", promhttp.Handler()) err = http.Serve(ln, nil) if err != nil { log.Fatalf("unable to boot debug server: %v", err) } }
func main() { flag.Parse() log.Infoln("Starting snmp exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) // Bail early if the config is bad. c, err := LoadFile(*configFile) if err != nil { log.Fatalf("Error parsing config file: %s", err) } // Initilise metrics. for module, _ := range *c { snmpDuration.WithLabelValues(module) } http.Handle("/metrics", promhttp.Handler()) // Normal metrics endpoint for SNMP exporter itself. http.HandleFunc("/snmp", handler) // Endpoint to do SNMP scrapes. log.Infof("Listening on %s", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() start := time.Now() oscillationFactor := func() float64 { return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(*oscillationPeriod))) } // Periodically record some sample latencies for the three services. go func() { for { v := rand.Float64() * *uniformDomain rpcDurations.WithLabelValues("uniform").Observe(v) time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond) } }() go func() { for { v := (rand.NormFloat64() * *normDomain) + *normMean rpcDurations.WithLabelValues("normal").Observe(v) rpcDurationsHistogram.Observe(v) time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond) } }() go func() { for { v := rand.ExpFloat64() / 1e6 rpcDurations.WithLabelValues("exponential").Observe(v) time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond) } }() // Expose the registered metrics via HTTP. http.Handle("/metrics", promhttp.Handler()) log.Fatal(http.ListenAndServe(*addr, nil)) }
// MakeHTTPHandler mounts the endpoints into a REST-y HTTP handler. func MakeHTTPHandler(ctx context.Context, e Endpoints, logger log.Logger) http.Handler { r := mux.NewRouter().StrictSlash(false) options := []httptransport.ServerOption{ httptransport.ServerErrorLogger(logger), httptransport.ServerErrorEncoder(encodeError), } // GET /login Login // GET /register Register // GET /health Health Check r.Methods("GET").Path("/login").Handler(httptransport.NewServer( ctx, e.LoginEndpoint, decodeLoginRequest, encodeResponse, options..., )) r.Methods("POST").Path("/register").Handler(httptransport.NewServer( ctx, e.RegisterEndpoint, decodeRegisterRequest, encodeResponse, options..., )) r.Methods("GET").PathPrefix("/customers").Handler(httptransport.NewServer( ctx, e.UserGetEndpoint, decodeGetRequest, encodeResponse, options..., )) r.Methods("GET").PathPrefix("/cards").Handler(httptransport.NewServer( ctx, e.CardGetEndpoint, decodeGetRequest, encodeResponse, options..., )) r.Methods("GET").PathPrefix("/addresses").Handler(httptransport.NewServer( ctx, e.AddressGetEndpoint, decodeGetRequest, encodeResponse, options..., )) r.Methods("POST").Path("/customers").Handler(httptransport.NewServer( ctx, e.UserPostEndpoint, decodeUserRequest, encodeResponse, options..., )) r.Methods("POST").Path("/addresses").Handler(httptransport.NewServer( ctx, e.AddressPostEndpoint, decodeAddressRequest, encodeResponse, options..., )) r.Methods("POST").Path("/cards").Handler(httptransport.NewServer( ctx, e.CardPostEndpoint, decodeCardRequest, encodeResponse, options..., )) r.Methods("DELETE").PathPrefix("/").Handler(httptransport.NewServer( ctx, e.DeleteEndpoint, decodeDeleteRequest, encodeResponse, options..., )) r.Methods("GET").PathPrefix("/health").Handler(httptransport.NewServer( ctx, e.HealthEndpoint, decodeHealthRequest, encodeHealthResponse, options..., )) r.Handle("/metrics", promhttp.Handler()) return r }
func main() { // Flag domain. fs := pflag.NewFlagSet("default", pflag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "DESCRIPTION\n") fmt.Fprintf(os.Stderr, " fluxd is the agent of flux.\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "FLAGS\n") fs.PrintDefaults() } // This mirrors how kubectl extracts information from the environment. var ( listenAddr = fs.StringP("listen", "l", ":3031", "Listen address where /metrics will be served") fluxsvcAddress = fs.String("fluxsvc-address", "wss://cloud.weave.works/api/flux", "Address of the fluxsvc to connect to.") token = fs.String("token", "", "Token to use to authenticate with flux service") kubernetesKubectl = fs.String("kubernetes-kubectl", "", "Optional, explicit path to kubectl tool") ) fs.Parse(os.Args) // Logger component. var logger log.Logger { logger = log.NewLogfmtLogger(os.Stderr) logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC) logger = log.NewContext(logger).With("caller", log.DefaultCaller) } // Platform component. var k8s platform.Platform { restClientConfig, err := restclient.InClusterConfig() if err != nil { logger.Log("err", err) os.Exit(1) } // When adding a new platform, don't just bash it in. Create a Platform // or Cluster interface in package platform, and have kubernetes.Cluster // and your new platform implement that interface. logger := log.NewContext(logger).With("component", "platform") logger.Log("host", restClientConfig.Host) cluster, err := kubernetes.NewCluster(restClientConfig, *kubernetesKubectl, logger) if err != nil { logger.Log("err", err) os.Exit(1) } if services, err := cluster.AllServices("", nil); err != nil { logger.Log("services", err) } else { logger.Log("services", len(services)) } k8s = cluster } // Instrumentation var ( daemonMetrics transport.DaemonMetrics ) { k8s = platform.Instrument(k8s, platform.NewMetrics()) daemonMetrics.ConnectionDuration = prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ Namespace: "flux", Subsystem: "fluxd", Name: "connection_duration_seconds", Help: "Duration in seconds of the current connection to fluxsvc. Zero means unconnected.", }, []string{"target"}) } // Connect to fluxsvc daemonLogger := log.NewContext(logger).With("component", "client") daemon, err := transport.NewDaemon( http.DefaultClient, flux.Token(*token), transport.NewRouter(), *fluxsvcAddress, k8s, daemonLogger, daemonMetrics, ) if err != nil { logger.Log("err", err) os.Exit(1) } defer daemon.Close() // Mechanical components. errc := make(chan error) go func() { c := make(chan os.Signal) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) errc <- fmt.Errorf("%s", <-c) }() // HTTP transport component, for metrics go func() { logger.Log("addr", *listenAddr) mux := http.NewServeMux() mux.Handle("/metrics", promhttp.Handler()) errc <- http.ListenAndServe(*listenAddr, mux) }() // Go! logger.Log("exiting", <-errc) }
func main() { // Flag domain. fs := pflag.NewFlagSet("default", pflag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "DESCRIPTION\n") fmt.Fprintf(os.Stderr, " fluxsvc is a deployment service.\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "FLAGS\n") fs.PrintDefaults() } var ( listenAddr = fs.StringP("listen", "l", ":3030", "Listen address for Flux API clients") databaseSource = fs.String("database-source", "file://fluxy.db", `Database source name; includes the DB driver as the scheme. The default is a temporary, file-based DB`) databaseMigrationsDir = fs.String("database-migrations", "./db/migrations", "Path to database migration scripts, which are in subdirectories named for each driver") natsURL = fs.String("nats-url", "", `URL on which to connect to NATS, or empty to use the standalone message bus (e.g., "nats://*****:*****@nats:4222")`) ) fs.Parse(os.Args) // Logger component. var logger log.Logger { logger = log.NewLogfmtLogger(os.Stderr) logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC) logger = log.NewContext(logger).With("caller", log.DefaultCaller) } // Initialise database; we must fail if we can't do this, because // most things depend on it. var dbDriver string { var version uint64 u, err := url.Parse(*databaseSource) if err == nil { version, err = db.Migrate(*databaseSource, *databaseMigrationsDir) } if err != nil { logger.Log("stage", "db init", "err", err) os.Exit(1) } dbDriver = db.DriverForScheme(u.Scheme) logger.Log("migrations", "success", "driver", dbDriver, "db-version", fmt.Sprintf("%d", version)) } // Instrumentation var ( httpDuration metrics.Histogram serverMetrics server.Metrics releaseMetrics release.Metrics helperDuration metrics.Histogram busMetrics platform.BusMetrics ) { httpDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "http_request_duration_seconds", Help: "HTTP request duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"method", "status_code"}) serverMetrics.ListServicesDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "list_services_duration_seconds", Help: "ListServices method duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"namespace", "success"}) serverMetrics.ListImagesDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "list_images_duration_seconds", Help: "ListImages method duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"service_spec", "success"}) serverMetrics.HistoryDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "history_duration_seconds", Help: "History method duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"service_spec", "success"}) serverMetrics.RegisterDaemonDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "register_daemon_duration_seconds", Help: "RegisterDaemon method duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"instance_id", "success"}) serverMetrics.ConnectedDaemons = prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "connected_daemons_count", Help: "Gauge of the current number of connected daemons", }, []string{}) serverMetrics.PlatformMetrics = platform.NewMetrics() releaseMetrics.ReleaseDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "release_duration_seconds", Help: "Release method duration in seconds.", Buckets: stdprometheus.DefBuckets, }, []string{"release_type", "release_kind", "success"}) releaseMetrics.ActionDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "release_action_duration_seconds", Help: "Duration in seconds of each sub-action invoked as part of a non-dry-run release.", Buckets: stdprometheus.DefBuckets, }, []string{"action", "success"}) releaseMetrics.StageDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "release_stage_duration_seconds", Help: "Duration in seconds of each stage of a release, including dry-runs.", Buckets: stdprometheus.DefBuckets, }, []string{"method", "stage"}) helperDuration = prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: "flux", Subsystem: "fluxsvc", Name: "release_helper_duration_seconds", Help: "Duration in seconds of a variety of release helper methods.", Buckets: stdprometheus.DefBuckets, }, []string{"method", "success"}) busMetrics = platform.NewBusMetrics() } var messageBus platform.MessageBus { if *natsURL != "" { bus, err := nats.NewMessageBus(*natsURL, busMetrics) if err != nil { logger.Log("component", "message bus", "err", err) os.Exit(1) } logger.Log("component", "message bus", "type", "NATS") messageBus = bus } else { messageBus = platform.NewStandaloneMessageBus(busMetrics) logger.Log("component", "message bus", "type", "standalone") } } var historyDB history.DB { db, err := historysql.NewSQL(dbDriver, *databaseSource) if err != nil { logger.Log("component", "history", "err", err) os.Exit(1) } historyDB = db } // Configuration, i.e., whether services are automated or not. var instanceDB instance.DB { db, err := instancedb.New(dbDriver, *databaseSource) if err != nil { logger.Log("component", "config", "err", err) os.Exit(1) } instanceDB = db } var instancer instance.Instancer { // Instancer, for the instancing of operations instancer = &instance.MultitenantInstancer{ DB: instanceDB, Connecter: messageBus, Logger: logger, Histogram: helperDuration, History: historyDB, } } // Job store. var jobStore jobs.JobStore { s, err := jobs.NewDatabaseStore(dbDriver, *databaseSource, time.Hour) if err != nil { logger.Log("component", "release job store", "err", err) os.Exit(1) } jobStore = s } // Automator component. var auto *automator.Automator { var err error auto, err = automator.New(automator.Config{ Jobs: jobStore, InstanceDB: instanceDB, Logger: log.NewContext(logger).With("component", "automator"), }) if err == nil { logger.Log("automator", "enabled") } else { // Service can handle a nil automator pointer. logger.Log("automator", "disabled", "reason", err) } } go auto.Start(log.NewContext(logger).With("component", "automator")) // Job workers. { logger := log.NewContext(logger).With("component", "worker") worker := jobs.NewWorker(jobStore, logger) worker.Register(jobs.AutomatedServiceJob, auto) worker.Register(jobs.ReleaseJob, release.NewReleaser(instancer, releaseMetrics)) defer func() { if err := worker.Stop(shutdownTimeout); err != nil { logger.Log("err", err) } }() go worker.Work() cleaner := jobs.NewCleaner(jobStore, logger) cleanTicker := time.NewTicker(15 * time.Second) defer cleanTicker.Stop() go cleaner.Clean(cleanTicker.C) } // The server. server := server.New(instancer, messageBus, jobStore, logger, serverMetrics) // Mechanical components. errc := make(chan error) go func() { c := make(chan os.Signal) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) errc <- fmt.Errorf("%s", <-c) }() // HTTP transport component. go func() { logger.Log("addr", *listenAddr) mux := http.NewServeMux() mux.Handle("/metrics", promhttp.Handler()) mux.Handle("/", transport.NewHandler(server, transport.NewRouter(), logger, httpDuration)) errc <- http.ListenAndServe(*listenAddr, mux) }() logger.Log("exiting", <-errc) }
func main() { flag.Parse() http.Handle("/metrics", promhttp.Handler()) log.Fatal(http.ListenAndServe(*addr, nil)) }
// RunServer starts tsuru API server. The dry parameter indicates whether the // server should run in dry mode, not starting the HTTP listener (for testing // purposes). func RunServer(dry bool) http.Handler { log.Init() connString, err := config.GetString("database:url") if err != nil { connString = db.DefaultDatabaseURL } dbName, err := config.GetString("database:name") if err != nil { dbName = db.DefaultDatabaseName } if !dry { fmt.Printf("Using mongodb database %q from the server %q.\n", dbName, connString) } m := apiRouter.NewRouter() for _, handler := range tsuruHandlerList { m.Add("1.0", handler.method, handler.path, handler.h) } if disableIndex, _ := config.GetBool("disable-index-page"); !disableIndex { m.Add("1.0", "Get", "/", Handler(index)) } m.Add("1.0", "Get", "/info", Handler(info)) m.Add("1.0", "Get", "/services/instances", AuthorizationRequiredHandler(serviceInstances)) m.Add("1.0", "Get", "/services/{service}/instances/{instance}", AuthorizationRequiredHandler(serviceInstance)) m.Add("1.0", "Delete", "/services/{service}/instances/{instance}", AuthorizationRequiredHandler(removeServiceInstance)) m.Add("1.0", "Post", "/services/{service}/instances", AuthorizationRequiredHandler(createServiceInstance)) m.Add("1.0", "Put", "/services/{service}/instances/{instance}", AuthorizationRequiredHandler(updateServiceInstance)) m.Add("1.0", "Put", "/services/{service}/instances/{instance}/{app}", AuthorizationRequiredHandler(bindServiceInstance)) m.Add("1.0", "Delete", "/services/{service}/instances/{instance}/{app}", AuthorizationRequiredHandler(unbindServiceInstance)) m.Add("1.0", "Get", "/services/{service}/instances/{instance}/status", AuthorizationRequiredHandler(serviceInstanceStatus)) m.Add("1.0", "Put", "/services/{service}/instances/permission/{instance}/{team}", AuthorizationRequiredHandler(serviceInstanceGrantTeam)) m.Add("1.0", "Delete", "/services/{service}/instances/permission/{instance}/{team}", AuthorizationRequiredHandler(serviceInstanceRevokeTeam)) m.AddAll("1.0", "/services/{service}/proxy/{instance}", AuthorizationRequiredHandler(serviceInstanceProxy)) m.AddAll("1.0", "/services/proxy/service/{service}", AuthorizationRequiredHandler(serviceProxy)) m.Add("1.0", "Get", "/services", AuthorizationRequiredHandler(serviceList)) m.Add("1.0", "Post", "/services", AuthorizationRequiredHandler(serviceCreate)) m.Add("1.0", "Put", "/services/{name}", AuthorizationRequiredHandler(serviceUpdate)) m.Add("1.0", "Delete", "/services/{name}", AuthorizationRequiredHandler(serviceDelete)) m.Add("1.0", "Get", "/services/{name}", AuthorizationRequiredHandler(serviceInfo)) m.Add("1.0", "Get", "/services/{name}/plans", AuthorizationRequiredHandler(servicePlans)) m.Add("1.0", "Get", "/services/{name}/doc", AuthorizationRequiredHandler(serviceDoc)) m.Add("1.0", "Put", "/services/{name}/doc", AuthorizationRequiredHandler(serviceAddDoc)) m.Add("1.0", "Put", "/services/{service}/team/{team}", AuthorizationRequiredHandler(grantServiceAccess)) m.Add("1.0", "Delete", "/services/{service}/team/{team}", AuthorizationRequiredHandler(revokeServiceAccess)) m.Add("1.0", "Delete", "/apps/{app}", AuthorizationRequiredHandler(appDelete)) m.Add("1.0", "Get", "/apps/{app}", AuthorizationRequiredHandler(appInfo)) m.Add("1.0", "Post", "/apps/{app}/cname", AuthorizationRequiredHandler(setCName)) m.Add("1.0", "Delete", "/apps/{app}/cname", AuthorizationRequiredHandler(unsetCName)) runHandler := AuthorizationRequiredHandler(runCommand) m.Add("1.0", "Post", "/apps/{app}/run", runHandler) m.Add("1.0", "Post", "/apps/{app}/restart", AuthorizationRequiredHandler(restart)) m.Add("1.0", "Post", "/apps/{app}/start", AuthorizationRequiredHandler(start)) m.Add("1.0", "Post", "/apps/{app}/stop", AuthorizationRequiredHandler(stop)) m.Add("1.0", "Post", "/apps/{app}/sleep", AuthorizationRequiredHandler(sleep)) m.Add("1.0", "Get", "/apps/{appname}/quota", AuthorizationRequiredHandler(getAppQuota)) m.Add("1.0", "Put", "/apps/{appname}/quota", AuthorizationRequiredHandler(changeAppQuota)) m.Add("1.0", "Put", "/apps/{appname}", AuthorizationRequiredHandler(updateApp)) m.Add("1.0", "Get", "/apps/{app}/env", AuthorizationRequiredHandler(getEnv)) m.Add("1.0", "Post", "/apps/{app}/env", AuthorizationRequiredHandler(setEnv)) m.Add("1.0", "Delete", "/apps/{app}/env", AuthorizationRequiredHandler(unsetEnv)) m.Add("1.0", "Get", "/apps", AuthorizationRequiredHandler(appList)) m.Add("1.0", "Post", "/apps", AuthorizationRequiredHandler(createApp)) forceDeleteLockHandler := AuthorizationRequiredHandler(forceDeleteLock) m.Add("1.0", "Delete", "/apps/{app}/lock", forceDeleteLockHandler) m.Add("1.0", "Put", "/apps/{app}/units", AuthorizationRequiredHandler(addUnits)) m.Add("1.0", "Delete", "/apps/{app}/units", AuthorizationRequiredHandler(removeUnits)) registerUnitHandler := AuthorizationRequiredHandler(registerUnit) m.Add("1.0", "Post", "/apps/{app}/units/register", registerUnitHandler) setUnitStatusHandler := AuthorizationRequiredHandler(setUnitStatus) m.Add("1.0", "Post", "/apps/{app}/units/{unit}", setUnitStatusHandler) m.Add("1.0", "Put", "/apps/{app}/teams/{team}", AuthorizationRequiredHandler(grantAppAccess)) m.Add("1.0", "Delete", "/apps/{app}/teams/{team}", AuthorizationRequiredHandler(revokeAppAccess)) m.Add("1.0", "Get", "/apps/{app}/log", AuthorizationRequiredHandler(appLog)) logPostHandler := AuthorizationRequiredHandler(addLog) m.Add("1.0", "Post", "/apps/{app}/log", logPostHandler) m.Add("1.0", "Post", "/apps/{appname}/deploy/rollback", AuthorizationRequiredHandler(deployRollback)) m.Add("1.0", "Get", "/apps/{app}/metric/envs", AuthorizationRequiredHandler(appMetricEnvs)) m.Add("1.0", "Post", "/apps/{app}/routes", AuthorizationRequiredHandler(appRebuildRoutes)) m.Add("1.0", "Post", "/node/status", AuthorizationRequiredHandler(setNodeStatus)) m.Add("1.0", "Get", "/deploys", AuthorizationRequiredHandler(deploysList)) m.Add("1.0", "Get", "/deploys/{deploy}", AuthorizationRequiredHandler(deployInfo)) m.Add("1.1", "Get", "/events", AuthorizationRequiredHandler(eventList)) m.Add("1.1", "Get", "/events/kinds", AuthorizationRequiredHandler(kindList)) m.Add("1.1", "Get", "/events/{uuid}", AuthorizationRequiredHandler(eventInfo)) m.Add("1.1", "Post", "/events/{uuid}/cancel", AuthorizationRequiredHandler(eventCancel)) m.Add("1.0", "Get", "/platforms", AuthorizationRequiredHandler(platformList)) m.Add("1.0", "Post", "/platforms", AuthorizationRequiredHandler(platformAdd)) m.Add("1.0", "Put", "/platforms/{name}", AuthorizationRequiredHandler(platformUpdate)) m.Add("1.0", "Delete", "/platforms/{name}", AuthorizationRequiredHandler(platformRemove)) // These handlers don't use {app} on purpose. Using :app means that only // the token generate for the given app is valid, but these handlers // use a token generated for Gandalf. m.Add("1.0", "Post", "/apps/{appname}/repository/clone", AuthorizationRequiredHandler(deploy)) m.Add("1.0", "Post", "/apps/{appname}/deploy", AuthorizationRequiredHandler(deploy)) diffDeployHandler := AuthorizationRequiredHandler(diffDeploy) m.Add("1.0", "Post", "/apps/{appname}/diff", diffDeployHandler) // Shell also doesn't use {app} on purpose. Middlewares don't play well // with websocket. m.Add("1.0", "Get", "/apps/{appname}/shell", websocket.Handler(remoteShellHandler)) m.Add("1.0", "Get", "/users", AuthorizationRequiredHandler(listUsers)) m.Add("1.0", "Post", "/users", Handler(createUser)) m.Add("1.0", "Get", "/users/info", AuthorizationRequiredHandler(userInfo)) m.Add("1.0", "Get", "/auth/scheme", Handler(authScheme)) m.Add("1.0", "Post", "/auth/login", Handler(login)) m.Add("1.0", "Post", "/auth/saml", Handler(samlCallbackLogin)) m.Add("1.0", "Get", "/auth/saml", Handler(samlMetadata)) m.Add("1.0", "Post", "/users/{email}/password", Handler(resetPassword)) m.Add("1.0", "Post", "/users/{email}/tokens", Handler(login)) m.Add("1.0", "Get", "/users/{email}/quota", AuthorizationRequiredHandler(getUserQuota)) m.Add("1.0", "Put", "/users/{email}/quota", AuthorizationRequiredHandler(changeUserQuota)) m.Add("1.0", "Delete", "/users/tokens", AuthorizationRequiredHandler(logout)) m.Add("1.0", "Put", "/users/password", AuthorizationRequiredHandler(changePassword)) m.Add("1.0", "Delete", "/users", AuthorizationRequiredHandler(removeUser)) m.Add("1.0", "Get", "/users/keys", AuthorizationRequiredHandler(listKeys)) m.Add("1.0", "Post", "/users/keys", AuthorizationRequiredHandler(addKeyToUser)) m.Add("1.0", "Delete", "/users/keys/{key}", AuthorizationRequiredHandler(removeKeyFromUser)) m.Add("1.0", "Get", "/users/api-key", AuthorizationRequiredHandler(showAPIToken)) m.Add("1.0", "Post", "/users/api-key", AuthorizationRequiredHandler(regenerateAPIToken)) m.Add("1.0", "Get", "/logs", websocket.Handler(addLogs)) m.Add("1.0", "Get", "/teams", AuthorizationRequiredHandler(teamList)) m.Add("1.0", "Post", "/teams", AuthorizationRequiredHandler(createTeam)) m.Add("1.0", "Delete", "/teams/{name}", AuthorizationRequiredHandler(removeTeam)) m.Add("1.0", "Post", "/swap", AuthorizationRequiredHandler(swap)) m.Add("1.0", "Get", "/healthcheck/", http.HandlerFunc(healthcheck)) m.Add("1.0", "Get", "/healthcheck", http.HandlerFunc(healthcheck)) m.Add("1.0", "Get", "/iaas/machines", AuthorizationRequiredHandler(machinesList)) m.Add("1.0", "Delete", "/iaas/machines/{machine_id}", AuthorizationRequiredHandler(machineDestroy)) m.Add("1.0", "Get", "/iaas/templates", AuthorizationRequiredHandler(templatesList)) m.Add("1.0", "Post", "/iaas/templates", AuthorizationRequiredHandler(templateCreate)) m.Add("1.0", "Put", "/iaas/templates/{template_name}", AuthorizationRequiredHandler(templateUpdate)) m.Add("1.0", "Delete", "/iaas/templates/{template_name}", AuthorizationRequiredHandler(templateDestroy)) m.Add("1.0", "Get", "/plans", AuthorizationRequiredHandler(listPlans)) m.Add("1.0", "Post", "/plans", AuthorizationRequiredHandler(addPlan)) m.Add("1.0", "Delete", "/plans/{planname}", AuthorizationRequiredHandler(removePlan)) m.Add("1.0", "Get", "/plans/routers", AuthorizationRequiredHandler(listRouters)) m.Add("1.0", "Get", "/pools", AuthorizationRequiredHandler(poolList)) m.Add("1.0", "Post", "/pools", AuthorizationRequiredHandler(addPoolHandler)) m.Add("1.0", "Delete", "/pools/{name}", AuthorizationRequiredHandler(removePoolHandler)) m.Add("1.0", "Put", "/pools/{name}", AuthorizationRequiredHandler(poolUpdateHandler)) m.Add("1.0", "Post", "/pools/{name}/team", AuthorizationRequiredHandler(addTeamToPoolHandler)) m.Add("1.0", "Delete", "/pools/{name}/team", AuthorizationRequiredHandler(removeTeamToPoolHandler)) m.Add("1.0", "Get", "/roles", AuthorizationRequiredHandler(listRoles)) m.Add("1.0", "Post", "/roles", AuthorizationRequiredHandler(addRole)) m.Add("1.0", "Get", "/roles/{name}", AuthorizationRequiredHandler(roleInfo)) m.Add("1.0", "Delete", "/roles/{name}", AuthorizationRequiredHandler(removeRole)) m.Add("1.0", "Post", "/roles/{name}/permissions", AuthorizationRequiredHandler(addPermissions)) m.Add("1.0", "Delete", "/roles/{name}/permissions/{permission}", AuthorizationRequiredHandler(removePermissions)) m.Add("1.0", "Post", "/roles/{name}/user", AuthorizationRequiredHandler(assignRole)) m.Add("1.0", "Delete", "/roles/{name}/user/{email}", AuthorizationRequiredHandler(dissociateRole)) m.Add("1.0", "Get", "/role/default", AuthorizationRequiredHandler(listDefaultRoles)) m.Add("1.0", "Post", "/role/default", AuthorizationRequiredHandler(addDefaultRole)) m.Add("1.0", "Delete", "/role/default", AuthorizationRequiredHandler(removeDefaultRole)) m.Add("1.0", "Get", "/permissions", AuthorizationRequiredHandler(listPermissions)) m.Add("1.0", "Get", "/debug/goroutines", AuthorizationRequiredHandler(dumpGoroutines)) m.Add("1.0", "Get", "/debug/pprof/", AuthorizationRequiredHandler(indexHandler)) m.Add("1.0", "Get", "/debug/pprof/cmdline", AuthorizationRequiredHandler(cmdlineHandler)) m.Add("1.0", "Get", "/debug/pprof/profile", AuthorizationRequiredHandler(profileHandler)) m.Add("1.0", "Get", "/debug/pprof/symbol", AuthorizationRequiredHandler(symbolHandler)) m.Add("1.0", "Get", "/debug/pprof/heap", AuthorizationRequiredHandler(indexHandler)) m.Add("1.0", "Get", "/debug/pprof/goroutine", AuthorizationRequiredHandler(indexHandler)) m.Add("1.0", "Get", "/debug/pprof/threadcreate", AuthorizationRequiredHandler(indexHandler)) m.Add("1.0", "Get", "/debug/pprof/block", AuthorizationRequiredHandler(indexHandler)) m.Add("1.0", "Get", "/debug/pprof/trace", AuthorizationRequiredHandler(traceHandler)) m.Add("1.2", "GET", "/node", AuthorizationRequiredHandler(listNodesHandler)) m.Add("1.2", "GET", "/node/apps/{appname}/containers", AuthorizationRequiredHandler(listUnitsByApp)) m.Add("1.2", "GET", "/node/{address:.*}/containers", AuthorizationRequiredHandler(listUnitsByNode)) m.Add("1.2", "POST", "/node", AuthorizationRequiredHandler(addNodeHandler)) m.Add("1.2", "PUT", "/node", AuthorizationRequiredHandler(updateNodeHandler)) m.Add("1.2", "DELETE", "/node/{address:.*}", AuthorizationRequiredHandler(removeNodeHandler)) m.Add("1.2", "GET", "/nodecontainers", AuthorizationRequiredHandler(nodeContainerList)) m.Add("1.2", "POST", "/nodecontainers", AuthorizationRequiredHandler(nodeContainerCreate)) m.Add("1.2", "GET", "/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerInfo)) m.Add("1.2", "DELETE", "/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerDelete)) m.Add("1.2", "POST", "/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerUpdate)) m.Add("1.2", "POST", "/nodecontainers/{name}/upgrade", AuthorizationRequiredHandler(nodeContainerUpgrade)) m.Add("1.2", "POST", "/install/hosts", AuthorizationRequiredHandler(installHostAdd)) m.Add("1.2", "GET", "/install/hosts", AuthorizationRequiredHandler(installHostList)) m.Add("1.2", "GET", "/install/hosts/{name}", AuthorizationRequiredHandler(installHostInfo)) m.Add("1.2", "GET", "/healing/node", AuthorizationRequiredHandler(nodeHealingRead)) m.Add("1.2", "POST", "/healing/node", AuthorizationRequiredHandler(nodeHealingUpdate)) m.Add("1.2", "DELETE", "/healing/node", AuthorizationRequiredHandler(nodeHealingDelete)) m.Add("1.2", "GET", "/metrics", promhttp.Handler()) // Handlers for compatibility reasons, should be removed on tsuru 2.0. m.Add("1.0", "GET", "/docker/node", AuthorizationRequiredHandler(listNodesHandler)) m.Add("1.0", "GET", "/docker/node/apps/{appname}/containers", AuthorizationRequiredHandler(listUnitsByApp)) m.Add("1.0", "GET", "/docker/node/{address:.*}/containers", AuthorizationRequiredHandler(listUnitsByNode)) m.Add("1.0", "POST", "/docker/node", AuthorizationRequiredHandler(addNodeHandler)) m.Add("1.0", "PUT", "/docker/node", AuthorizationRequiredHandler(updateNodeHandler)) m.Add("1.0", "DELETE", "/docker/node/{address:.*}", AuthorizationRequiredHandler(removeNodeHandler)) m.Add("1.0", "GET", "/docker/nodecontainers", AuthorizationRequiredHandler(nodeContainerList)) m.Add("1.0", "POST", "/docker/nodecontainers", AuthorizationRequiredHandler(nodeContainerCreate)) m.Add("1.0", "GET", "/docker/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerInfo)) m.Add("1.0", "DELETE", "/docker/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerDelete)) m.Add("1.0", "POST", "/docker/nodecontainers/{name}", AuthorizationRequiredHandler(nodeContainerUpdate)) m.Add("1.0", "POST", "/docker/nodecontainers/{name}/upgrade", AuthorizationRequiredHandler(nodeContainerUpgrade)) m.Add("1.0", "GET", "/docker/healing/node", AuthorizationRequiredHandler(nodeHealingRead)) m.Add("1.0", "POST", "/docker/healing/node", AuthorizationRequiredHandler(nodeHealingUpdate)) m.Add("1.0", "DELETE", "/docker/healing/node", AuthorizationRequiredHandler(nodeHealingDelete)) n := negroni.New() n.Use(negroni.NewRecovery()) n.Use(negroni.HandlerFunc(contextClearerMiddleware)) if !dry { n.Use(newLoggerMiddleware()) } n.UseHandler(m) n.Use(negroni.HandlerFunc(flushingWriterMiddleware)) n.Use(negroni.HandlerFunc(setRequestIDHeaderMiddleware)) n.Use(negroni.HandlerFunc(errorHandlingMiddleware)) n.Use(negroni.HandlerFunc(setVersionHeadersMiddleware)) n.Use(negroni.HandlerFunc(authTokenMiddleware)) n.Use(&appLockMiddleware{excludedHandlers: []http.Handler{ logPostHandler, runHandler, forceDeleteLockHandler, registerUnitHandler, setUnitStatusHandler, diffDeployHandler, }}) n.UseHandler(http.HandlerFunc(runDelayedHandler)) if !dry { startServer(n) } return n }