diff --git a/CHANGELOG.md b/CHANGELOG.md index a81c8e682b3..f0a2c2ffe23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * `cortex_prometheus_notifications_queue_capacity` * `cortex_prometheus_notifications_alertmanagers_discovered` * [ENHANCEMENT] Added `-ingester.flush-on-shutdown-with-wal-enabled` option to enable chunks flushing even when WAL is enabled. #2780 +* [ENHANCEMENT] Query-tee: Support for custom API prefix by using `-server.path-prefix` option. #2814 * [BUGFIX] Fixed a bug in the index intersect code causing storage to return more chunks/series than required. #2796 * [BUGFIX] Fixed the number of reported keys in the background cache queue. #2764 * [BUGFIX] Fix race in processing of headers in sharded queries. #2762 diff --git a/cmd/query-tee/main.go b/cmd/query-tee/main.go index f8ef82e6914..ac0d6438a30 100644 --- a/cmd/query-tee/main.go +++ b/cmd/query-tee/main.go @@ -17,12 +17,14 @@ type Config struct { ServerMetricsPort int LogLevel logging.Level ProxyConfig querytee.ProxyConfig + PathPrefix string } func main() { // Parse CLI flags. cfg := Config{} flag.IntVar(&cfg.ServerMetricsPort, "server.metrics-port", 9900, "The port where metrics are exposed.") + flag.StringVar(&cfg.PathPrefix, "server.path-prefix", "", "Prefix for API paths (query-tee will accept Prometheus API calls at /api/v1/...)") cfg.LogLevel.RegisterFlags(flag.CommandLine) cfg.ProxyConfig.RegisterFlags(flag.CommandLine) flag.Parse() @@ -42,7 +44,7 @@ func main() { } // Run the proxy. - proxy, err := querytee.NewProxy(cfg.ProxyConfig, util.Logger, cortexReadRoutes(), registry) + proxy, err := querytee.NewProxy(cfg.ProxyConfig, util.Logger, cortexReadRoutes(cfg.PathPrefix), registry) if err != nil { level.Error(util.Logger).Log("msg", "Unable to initialize the proxy", "err", err.Error()) os.Exit(1) @@ -56,16 +58,21 @@ func main() { proxy.Await() } -func cortexReadRoutes() []querytee.Route { +func cortexReadRoutes(prefix string) []querytee.Route { + // Strip trailing slashes. + for len(prefix) > 0 && prefix[len(prefix)-1] == '/' { + prefix = prefix[:len(prefix)-1] + } + samplesComparator := querytee.NewSamplesComparator() return []querytee.Route{ - {Path: "/api/v1/query", RouteName: "api_v1_query", Methods: []string{"GET"}, ResponseComparator: samplesComparator}, - {Path: "/api/v1/query_range", RouteName: "api_v1_query_range", Methods: []string{"GET"}, ResponseComparator: samplesComparator}, - {Path: "/api/v1/labels", RouteName: "api_v1_labels", Methods: []string{"GET"}, ResponseComparator: nil}, - {Path: "/api/v1/label/{name}/values", RouteName: "api_v1_label_name_values", Methods: []string{"GET"}, ResponseComparator: nil}, - {Path: "/api/v1/series", RouteName: "api_v1_series", Methods: []string{"GET"}, ResponseComparator: nil}, - {Path: "/api/v1/metadata", RouteName: "api_v1_metadata", Methods: []string{"GET"}, ResponseComparator: nil}, - {Path: "/api/v1/rules", RouteName: "api_v1_rules", Methods: []string{"GET"}, ResponseComparator: nil}, - {Path: "/api/v1/alerts", RouteName: "api_v1_alerts", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/query", RouteName: "api_v1_query", Methods: []string{"GET"}, ResponseComparator: samplesComparator}, + {Path: prefix + "/api/v1/query_range", RouteName: "api_v1_query_range", Methods: []string{"GET"}, ResponseComparator: samplesComparator}, + {Path: prefix + "/api/v1/labels", RouteName: "api_v1_labels", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/label/{name}/values", RouteName: "api_v1_label_name_values", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/series", RouteName: "api_v1_series", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/metadata", RouteName: "api_v1_metadata", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/rules", RouteName: "api_v1_rules", Methods: []string{"GET"}, ResponseComparator: nil}, + {Path: prefix + "/api/v1/alerts", RouteName: "api_v1_alerts", Methods: []string{"GET"}, ResponseComparator: nil}, } } diff --git a/cmd/query-tee/main_test.go b/cmd/query-tee/main_test.go new file mode 100644 index 00000000000..48c5347e694 --- /dev/null +++ b/cmd/query-tee/main_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCortexReadRoutes(t *testing.T) { + routes := cortexReadRoutes("") + for _, r := range routes { + assert.True(t, strings.HasPrefix(r.Path, "/api/v1/")) + } + + routes = cortexReadRoutes("/some/random/prefix///") + for _, r := range routes { + assert.True(t, strings.HasPrefix(r.Path, "/some/random/prefix/api/v1/")) + } +}