From 24c4d1c16a2f9e9780a11f896119cd04c263c157 Mon Sep 17 00:00:00 2001 From: Jared Kirschner Date: Wed, 31 May 2023 08:08:43 -0700 Subject: [PATCH 1/2] Accept ap, datacenter, and namespace query params This commit only contains the OSS PR (datacenter query param support). A separate enterprise PR adds support for ap and namespace query params. Resources in Consul can exists within scopes such as datacenters, cluster peers, admin partitions, and namespaces. You can refer to those resources from interfaces such as the CLI, HTTP API, DNS, and configuration files. Some scope levels have consistent naming: cluster peers are always referred to as "peer". Other scope levels use a short-hand in DNS lookups... - "ns" for namespace - "ap" for admin partition - "dc" for datacenter ...But use long-hand in CLI commands: - "namespace" for namespace - "partition" for admin partition - and "datacenter" However, HTTP API query parameters do not follow a consistent pattern, supporting short-hand for some scopes but long-hand for others: - "ns" for namespace - "partition" for admin partition - and "dc" for datacenter. This inconsistency is confusing, especially for users who have been exposed to providing scope names through another interface such as CLI or DNS queries. This commit improves UX by consistently supporting both short-hand and long-hand forms of the namespace, partition, and datacenter scopes in HTTP API query parameters. --- agent/http.go | 7 +++++-- agent/http_test.go | 9 +++++++++ api/api.go | 13 +++++++++++++ command/connect/envoy/envoy_test.go | 10 ++++++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/agent/http.go b/agent/http.go index 701674b5556..1706794adfe 100644 --- a/agent/http.go +++ b/agent/http.go @@ -983,9 +983,12 @@ func parseConsistencyReadRequest(resp http.ResponseWriter, req *http.Request, b } } -// parseDC is used to parse the ?dc query param +// parseDC is used to parse the datacenter from the query params. +// ?datacenter has precedence over ?dc. func (s *HTTPHandlers) parseDC(req *http.Request, dc *string) { - if other := req.URL.Query().Get("dc"); other != "" { + if other := req.URL.Query().Get("datacenter"); other != "" { + *dc = other + } else if other = req.URL.Query().Get("dc"); other != "" { *dc = other } else if *dc == "" { *dc = s.agent.config.Datacenter diff --git a/agent/http_test.go b/agent/http_test.go index 37acc5f8ee1..967b1b0b43b 100644 --- a/agent/http_test.go +++ b/agent/http_test.go @@ -881,6 +881,15 @@ func TestParseSource(t *testing.T) { t.Fatalf("bad: %v", source) } + // We should follow whatever datacenter parameter was given so that the node is + // looked up correctly on the receiving end. + req, _ = http.NewRequest("GET", "/v1/catalog/nodes?near=bob&datacenter=foo", nil) + source = structs.QuerySource{} + a.srv.parseSource(req, &source) + if source.Datacenter != "foo" || source.Node != "bob" { + t.Fatalf("bad: %v", source) + } + // The magic "_agent" node name will use the agent's local node name. req, _ = http.NewRequest("GET", "/v1/catalog/nodes?near=_agent", nil) source = structs.QuerySource{} diff --git a/api/api.go b/api/api.go index e7109141b50..1fe0c71b61e 100644 --- a/api/api.go +++ b/api/api.go @@ -836,12 +836,21 @@ func (r *request) setQueryOptions(q *QueryOptions) { return } if q.Namespace != "" { + // For backwards-compatibility with existing tests, + // use the short-hand query param name "ns" + // rather than the alternative long-hand "namespace" r.params.Set("ns", q.Namespace) } if q.Partition != "" { + // For backwards-compatibility with existing tests, + // use the long-hand query param name "partition" + // rather than the alternative short-hand "ap" r.params.Set("partition", q.Partition) } if q.Datacenter != "" { + // For backwards-compatibility with existing tests, + // use the short-hand query param name "dc" + // rather than the alternative long-hand "datacenter" r.params.Set("dc", q.Datacenter) } if q.Peer != "" { @@ -949,12 +958,16 @@ func (r *request) setWriteOptions(q *WriteOptions) { if q == nil { return } + // For backwards-compatibility, continue to use the shorthand "ns" + // rather than "namespace" if q.Namespace != "" { r.params.Set("ns", q.Namespace) } if q.Partition != "" { r.params.Set("partition", q.Partition) } + // For backwards-compatibility, continue to use the shorthand "dc" + // rather than "datacenter" if q.Datacenter != "" { r.params.Set("dc", q.Datacenter) } diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index d1105df0d2c..86c48a8e39e 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -1466,6 +1466,9 @@ func testMockAgentGatewayConfig(namespacesEnabled bool) http.HandlerFunc { func namespaceFromQuery(r *http.Request) string { // Use the namespace in the request if there is one, otherwise // use-default. + if queryNamespace := r.URL.Query().Get("namespace"); queryNamespace != "" { + return queryNamespace + } if queryNs := r.URL.Query().Get("ns"); queryNs != "" { return queryNs } @@ -1475,8 +1478,11 @@ func namespaceFromQuery(r *http.Request) string { func partitionFromQuery(r *http.Request) string { // Use the partition in the request if there is one, otherwise // use-default. - if queryAP := r.URL.Query().Get("partition"); queryAP != "" { - return queryAP + if queryPartition := r.URL.Query().Get("partition"); queryPartition != "" { + return queryPartition + } + if queryAp := r.URL.Query().Get("ap"); queryAp != "" { + return queryAp } return "default" } From b2d7c0a02367adf3bd4a733d28db80cadfef338c Mon Sep 17 00:00:00 2001 From: Jared Kirschner Date: Wed, 31 May 2023 08:19:02 -0700 Subject: [PATCH 2/2] Add changelog --- .changelog/17525.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/17525.txt diff --git a/.changelog/17525.txt b/.changelog/17525.txt new file mode 100644 index 00000000000..66bdcb8d900 --- /dev/null +++ b/.changelog/17525.txt @@ -0,0 +1,3 @@ +```release-note:improvement +http: accept query parameters `datacenter`, `ap` (enterprise-only), and `namespace` (enterprise-only). Both short-hand and long-hand forms of these query params are now supported via the HTTP API (dc/datacenter, ap/partition, ns/namespace). +``` \ No newline at end of file