// InitRESTRouter initializes a mux.Router with REST API // routes. func InitRESTRouter(r *mux.Router, versionMain string, mgr *cbgt.Manager, staticDir, staticETag string, mr *cbgt.MsgRing, assetDir func(name string) ([]string, error), asset func(name string) ([]byte, error)) ( *mux.Router, map[string]RESTMeta, error) { PIndexTypesInitRouter(r, "manager.before") meta := map[string]RESTMeta{} handle := func(path string, method string, h http.Handler, opts map[string]string) { if a, ok := h.(RESTOpts); ok { a.RESTOpts(opts) } meta[path+" "+RESTMethodOrds[method]+method] = RESTMeta{path, method, opts} r.Handle(path, h).Methods(method) } handleFunc := func(path string, method string, h http.HandlerFunc, opts map[string]string) { meta[path+" "+RESTMethodOrds[method]+method] = RESTMeta{path, method, opts} r.HandleFunc(path, h).Methods(method) } handle("/api/index", "GET", NewListIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Returns all index definitions as JSON.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "PUT", NewCreateIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Creates/updates an index definition.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "DELETE", NewDeleteIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Deletes an index definition.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "GET", NewGetIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Returns the definition of an index as JSON.`, "version introduced": "0.0.1", }) if mgr == nil || mgr.TagsMap() == nil || mgr.TagsMap()["queryer"] { handle("/api/index/{indexName}/count", "GET", NewCountHandler(mgr), map[string]string{ "_category": "Indexing|Index querying", "_about": `Returns the count of indexed documents.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/query", "POST", NewQueryHandler(mgr), map[string]string{ "_category": "Indexing|Index querying", "_about": `Queries an index.`, "version introduced": "0.2.0", }) } handle("/api/index/{indexName}/planFreezeControl/{op}", "POST", NewIndexControlHandler(mgr, "planFreeze", map[string]bool{ "freeze": true, "unfreeze": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Freeze the assignment of index partitions to nodes.`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "freeze" or "unfreeze".`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/ingestControl/{op}", "POST", NewIndexControlHandler(mgr, "write", map[string]bool{ "pause": true, "resume": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Pause index updates and maintenance (no more ingesting document mutations).`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "pause" or "resume".`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/queryControl/{op}", "POST", NewIndexControlHandler(mgr, "read", map[string]bool{ "allow": true, "disallow": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Disallow queries on an index.`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "allow" or "disallow".`, "version introduced": "0.0.1", }) if mgr == nil || mgr.TagsMap() == nil || mgr.TagsMap()["pindex"] { handle("/api/pindex", "GET", NewListPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition definition", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}", "GET", NewGetPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition definition", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}/count", "GET", NewCountPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition querying", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}/query", "POST", NewQueryPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition querying", "version introduced": "0.2.0", }) } handle("/api/cfg", "GET", NewCfgGetHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Returns the node's current view of the cluster's configuration as JSON.`, "version introduced": "0.0.1", }) handle("/api/cfgRefresh", "POST", NewCfgRefreshHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Requests the node to refresh its configuration from the configuration provider.`, "version introduced": "0.0.1", }) handle("/api/log", "GET", NewLogGetHandler(mgr, mr), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns recent log messages and key events for the node as JSON.`, "version introduced": "0.0.1", }) handle("/api/managerKick", "POST", NewManagerKickHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Forces the node to replan resource assignments (by running the planner, if enabled) and to update its runtime state to reflect the latest plan (by running the janitor, if enabled).`, "version introduced": "0.0.1", }) handle("/api/managerMeta", "GET", NewManagerMetaHandler(mgr, meta), map[string]string{ "_category": "Node|Node configuration", "_about": `Returns information on the node's capabilities, including available indexing and storage options as JSON, and is intended to help management tools and web UI's to be more dynamically metadata driven.`, "version introduced": "0.0.1", }) handle("/api/runtime", "GET", NewRuntimeGetHandler(versionMain, mgr), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns information on the node's software, such as version strings and slow-changing runtime settings as JSON.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/args", "GET", RESTGetRuntimeArgs, map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns information on the node's command-line, parameters, environment variables and O/S process values as JSON.`, "version introduced": "0.0.1", }) handle("/api/diag", "GET", NewDiagGetHandler(versionMain, mgr, mr, assetDir, asset), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns full set of diagnostic information from the node in one shot as JSON. That is, the /api/diag response will be the union of the responses from the other REST API diagnostic and monitoring endpoints from the node, and is intended to make production support easier.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/gc", "POST", RESTPostRuntimeGC, map[string]string{ "_category": "Node|Node management", "_about": `Requests the node to perform a GC.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/profile/cpu", "POST", RESTProfileCPU, map[string]string{ "_category": "Node|Node diagnostics", "_about": `Requests the node to capture local cpu usage profiling information.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/profile/memory", "POST", RESTProfileMemory, map[string]string{ "_category": "Node|Node diagnostics", "_about": `Requests the node to capture lcoal memory usage profiling information.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/stats", "GET", RESTGetRuntimeStats, map[string]string{ "_category": "Node|Node monitoring", "_about": `Returns information on the node's low-level runtime stats as JSON.`, "version introduced": "0.0.1", }) handleFunc("/api/runtime/statsMem", "GET", RESTGetRuntimeStatsMem, map[string]string{ "_category": "Node|Node monitoring", "_about": `Returns information on the node's low-level GC and memory related runtime stats as JSON.`, "version introduced": "0.0.1", }) handle("/api/stats", "GET", NewStatsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns indexing and data related metrics, timings and counters from the node as JSON.`, "version introduced": "0.0.1", }) // TODO: If we ever implement cluster-wide index stats, we should // have it under /api/index/{indexName}/stats GET endpoint. // handle("/api/stats/index/{indexName}", "GET", NewStatsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns metrics, timings and counters for a single index from the node as JSON.`, "version introduced": "0.0.1", }) PIndexTypesInitRouter(r, "manager.after") return r, meta, nil }
// InitRESTRouter initializes a mux.Router with REST API routes with // extra option. func InitRESTRouterEx(r *mux.Router, versionMain string, mgr *cbgt.Manager, staticDir, staticETag string, mr *cbgt.MsgRing, assetDir func(name string) ([]string, error), asset func(name string) ([]byte, error), options map[string]interface{}) ( *mux.Router, map[string]RESTMeta, error) { var authHandler func(http.Handler) http.Handler mapRESTPathStats := map[string]*RESTPathStats{} // Keyed by path spec. if options != nil { if v, ok := options["auth"]; ok { authHandler, ok = v.(func(http.Handler) http.Handler) if !ok { return nil, nil, fmt.Errorf("rest: auth function invalid") } } if v, ok := options["mapRESTPathStats"]; ok { mapRESTPathStats, ok = v.(map[string]*RESTPathStats) if !ok { return nil, nil, fmt.Errorf("rest: mapRESTPathStats invalid") } } } prefix := mgr.Options()["urlPrefix"] PIndexTypesInitRouter(r, "manager.before", mgr) meta := map[string]RESTMeta{} handle := func(path string, method string, h http.Handler, opts map[string]string) { opts["_path"] = path if a, ok := h.(RESTOpts); ok { a.RESTOpts(opts) } prefixPath := prefix + path restMeta := RESTMeta{prefixPath, method, opts} meta[prefixPath+" "+RESTMethodOrds[method]+method] = restMeta h = &HandlerWithRESTMeta{ h: h, RESTMeta: &restMeta, pathStats: mapRESTPathStats[path], focusName: PathFocusName(path), } if authHandler != nil { h = authHandler(h) } r.Handle(prefixPath, h).Methods(method).Name(prefixPath) } handle("/api/index", "GET", NewListIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Returns all index definitions as JSON.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "PUT", NewCreateIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Creates/updates an index definition.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "DELETE", NewDeleteIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Deletes an index definition.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}", "GET", NewGetIndexHandler(mgr), map[string]string{ "_category": "Indexing|Index definition", "_about": `Returns the definition of an index as JSON.`, "version introduced": "0.0.1", }) if mgr == nil || mgr.TagsMap() == nil || mgr.TagsMap()["queryer"] { handle("/api/index/{indexName}/count", "GET", NewCountHandler(mgr), map[string]string{ "_category": "Indexing|Index querying", "_about": `Returns the count of indexed documents.`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/query", "POST", NewQueryHandler(mgr, mapRESTPathStats["/api/index/{indexName}/query"]), map[string]string{ "_category": "Indexing|Index querying", "_about": `Queries an index.`, "version introduced": "0.2.0", }) } handle("/api/index/{indexName}/planFreezeControl/{op}", "POST", NewIndexControlHandler(mgr, "planFreeze", map[string]bool{ "freeze": true, "unfreeze": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Freeze the assignment of index partitions to nodes.`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "freeze" or "unfreeze".`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/ingestControl/{op}", "POST", NewIndexControlHandler(mgr, "write", map[string]bool{ "pause": true, "resume": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Pause index updates and maintenance (no more ingesting document mutations).`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "pause" or "resume".`, "version introduced": "0.0.1", }) handle("/api/index/{indexName}/queryControl/{op}", "POST", NewIndexControlHandler(mgr, "read", map[string]bool{ "allow": true, "disallow": true, }), map[string]string{ "_category": "Indexing|Index management", "_about": `Disallow queries on an index.`, "param: op": "required, string, URL path parameter\n\n" + `Allowed values for op are "allow" or "disallow".`, "version introduced": "0.0.1", }) if mgr == nil || mgr.TagsMap() == nil || mgr.TagsMap()["pindex"] { handle("/api/pindex", "GET", NewListPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition definition", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}", "GET", NewGetPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition definition", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}/count", "GET", NewCountPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition querying", "version introduced": "0.0.1", }) handle("/api/pindex/{pindexName}/query", "POST", NewQueryPIndexHandler(mgr), map[string]string{ "_category": "x/Advanced|x/Index partition querying", "version introduced": "0.2.0", }) } handle("/api/managerOptions", "PUT", NewManagerOptions(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": "Set the options for the manager", "version introduced": "4.2.0", }) handle("/api/cfg", "GET", NewCfgGetHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Returns the node's current view of the cluster's configuration as JSON.`, "version introduced": "0.0.1", }) handle("/api/cfgRefresh", "POST", NewCfgRefreshHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Requests the node to refresh its configuration from the configuration provider.`, "version introduced": "0.0.1", }) handle("/api/log", "GET", NewLogGetHandler(mgr, mr), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns recent log messages and key events for the node as JSON.`, "version introduced": "0.0.1", }) handle("/api/manager", "GET", NewManagerHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Returns runtime config information about this node.`, "version introduced": "0.4.0", }) handle("/api/managerKick", "POST", NewManagerKickHandler(mgr), map[string]string{ "_category": "Node|Node configuration", "_about": `Forces the node to replan resource assignments (by running the planner, if enabled) and to update its runtime state to reflect the latest plan (by running the janitor, if enabled).`, "version introduced": "0.0.1", }) handle("/api/managerMeta", "GET", NewManagerMetaHandler(mgr, meta), map[string]string{ "_category": "Node|Node configuration", "_about": `Returns information on the node's capabilities, including available indexing and storage options as JSON, and is intended to help management tools and web UI's to be more dynamically metadata driven.`, "version introduced": "0.0.1", }) handle("/api/runtime", "GET", NewRuntimeGetHandler(versionMain, mgr), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns information on the node's software, such as version strings and slow-changing runtime settings as JSON.`, "version introduced": "0.0.1", }) handle("/api/runtime/args", "GET", http.HandlerFunc(RESTGetRuntimeArgs), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns information on the node's command-line, parameters, environment variables and O/S process values as JSON.`, "version introduced": "0.0.1", }) handle("/api/diag", "GET", NewDiagGetHandler(versionMain, mgr, mr, assetDir, asset), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns full set of diagnostic information from the node in one shot as JSON. That is, the /api/diag response will be the union of the responses from the other REST API diagnostic and monitoring endpoints from the node, and is intended to make production support easier.`, "version introduced": "0.0.1", }) handle("/api/ping", "GET", &NoopHandler{}, map[string]string{ "_category": "Node|Node diagnostics", "_about": `Returns an empty body as a quick aliveness check.`, "version introduced": "5.0.0", }) handle("/api/runtime/gc", "POST", http.HandlerFunc(RESTPostRuntimeGC), map[string]string{ "_category": "Node|Node management", "_about": `Requests the node to perform a GC.`, "version introduced": "0.0.1", }) handle("/api/runtime/profile/cpu", "POST", http.HandlerFunc(RESTProfileCPU), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Requests the node to capture local cpu usage profiling information.`, "version introduced": "0.0.1", }) handle("/api/runtime/profile/memory", "POST", http.HandlerFunc(RESTProfileMemory), map[string]string{ "_category": "Node|Node diagnostics", "_about": `Requests the node to capture lcoal memory usage profiling information.`, "version introduced": "0.0.1", }) handle("/api/runtime/stats", "GET", http.HandlerFunc(RESTGetRuntimeStats), map[string]string{ "_category": "Node|Node monitoring", "_about": `Returns information on the node's low-level runtime stats as JSON.`, "version introduced": "0.0.1", }) handle("/api/runtime/statsMem", "GET", http.HandlerFunc(RESTGetRuntimeStatsMem), map[string]string{ "_category": "Node|Node monitoring", "_about": `Returns information on the node's low-level GC and memory related runtime stats as JSON.`, "version introduced": "0.0.1", }) handle("/api/stats", "GET", NewStatsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns indexing and data related metrics, timings and counters from the node as JSON.`, "version introduced": "0.0.1", }) // TODO: If we ever implement cluster-wide index stats, we should // have it under /api/index/{indexName}/stats GET endpoint. // handle("/api/stats/index/{indexName}", "GET", NewStatsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns metrics, timings and counters for a single index from the node as JSON.`, "version introduced": "0.0.1", }) handle("/api/stats/sourceStats/{indexName}", "GET", NewSourceStatsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns data source specific stats for an index as JSON.`, "version introduced": "4.2.0", }) handle("/api/stats/sourcePartitionSeqs/{indexName}", "GET", NewSourcePartitionSeqsHandler(mgr), map[string]string{ "_category": "Indexing|Index monitoring", "_about": `Returns data source partiton seqs for an index as JSON.`, "version introduced": "4.2.0", }) PIndexTypesInitRouter(r, "manager.after", mgr) return r, meta, nil }