579 lines
16 KiB
Plaintext
579 lines
16 KiB
Plaintext
---
|
|
layout: api
|
|
page_title: Discovery Chain - HTTP API
|
|
description: The /discovery-chain endpoints are for interacting with the discovery chain.
|
|
---
|
|
|
|
# Discovery Chain HTTP Endpoint
|
|
|
|
-> **1.6.0+:** The discovery chain API is available in Consul versions 1.6.0 and newer.
|
|
|
|
~> This is a low-level API primarily targeted at developers building external
|
|
[Connect proxy integrations](/docs/connect/proxies/integrate). Future
|
|
high-level proxy integration APIs may obviate the need for this API over time.
|
|
|
|
The `/discovery-chain` endpoint returns the compiled [discovery
|
|
chain](/docs/connect/l7-traffic/discovery-chain) for a service.
|
|
|
|
This will fetch all related [configuration
|
|
entries](/docs/agent/config-entries) and render them into a form suitable
|
|
for use by a [connect proxy](/docs/connect/proxies) implementation. This
|
|
is a key component of [L7 Traffic
|
|
Management](/docs/connect/l7-traffic).
|
|
|
|
## Read Compiled Discovery Chain
|
|
|
|
If overrides are needed they are passed as the JSON-encoded request body and
|
|
the `POST` method must be used, otherwise `GET` is sufficient.
|
|
|
|
| Method | Path | Produces |
|
|
| ------------------ | -------------------------------- | ------------------ |
|
|
| `GET` | `/discovery-chain/:service_name` | `application/json` |
|
|
| `POST`<sup>1</sup> | `/discovery-chain/:service_name` | `application/json` |
|
|
|
|
<p>
|
|
<sup>1</sup> Both GET and POST are for <strong>read</strong> operations. GET
|
|
requests do not permit request bodies so a POST is required if override
|
|
parameters are needed.
|
|
</p>
|
|
|
|
The table below shows this endpoint's support for
|
|
[blocking queries](/api-docs/features/blocking),
|
|
[consistency modes](/api-docs/features/consistency),
|
|
[agent caching](/api-docs/features/caching), and
|
|
[required ACLs](/api-docs/api-structure#authentication).
|
|
|
|
| Blocking Queries | Consistency Modes | Agent Caching | ACL Required |
|
|
| ---------------- | ----------------- | -------------------- | -------------- |
|
|
| `YES` | `all` | `background refresh` | `service:read` |
|
|
|
|
### Path Parameters
|
|
|
|
- `service_name` `(string: <required>)` - Specifies the service to query when
|
|
compiling the discovery chain.
|
|
|
|
### Query Parameters
|
|
|
|
- `compile-dc` `(string: "")` - Specifies the datacenter to use as the basis of
|
|
compilation. This will default to the datacenter of the agent being queried.
|
|
|
|
This value comes from an [upstream
|
|
configuration](/docs/connect/registration/service-registration#upstream-configuration-reference)
|
|
[`datacenter`](/docs/connect/registration/service-registration#datacenter)
|
|
parameter.
|
|
|
|
- `ns` `(string: "")` <EnterpriseAlert inline /> - Specifies the source namespace you use as the basis of compilation.
|
|
You can also [specify the namespace through other methods](#methods-to-specify-namespace).
|
|
|
|
### JSON Request Body Schema
|
|
|
|
- `OverrideConnectTimeout` `(duration: 0s)` - Overrides the final [connect
|
|
timeout](/docs/connect/config-entries/service-resolver#connecttimeout) for
|
|
any service resolved in the compiled chain.
|
|
|
|
This value comes from the `connect_timeout_ms` key in an [upstream
|
|
configuration](/docs/connect/registration/service-registration#upstream-configuration-reference)
|
|
opaque
|
|
[`config`](/docs/connect/registration/service-registration#config-1)
|
|
parameter.
|
|
|
|
- `OverrideProtocol` `(string: "")` - Overrides the final
|
|
[protocol](/docs/connect/config-entries/service-defaults#protocol) used in
|
|
the compiled discovery chain.
|
|
|
|
If the chain ordinarily would be TCP and an L7 protocol is passed here the
|
|
chain will still not include Routers or Splitters. If the chain ordinarily
|
|
would be L7 and TCP is passed here the chain will not include Routers or
|
|
Splitters.
|
|
|
|
This value comes from the `protocol` key in an [upstream
|
|
configuration](/docs/connect/registration/service-registration#upstream-configuration-reference)
|
|
opaque
|
|
[`config`](/docs/connect/registration/service-registration#config-1)
|
|
parameter.
|
|
|
|
- `OverrideMeshGateway` `(MeshGatewayConfig: <optional>)` - Overrides the final
|
|
[mesh gateway configuration](/docs/connect/gateways/mesh-gateway#connect-proxy-configuration)
|
|
for this any service resolved in the compiled chain.
|
|
|
|
This value comes from either the [proxy
|
|
configuration](/docs/connect/registration/service-registration#complete-configuration-example)
|
|
[`mesh_gateway`](/docs/connect/registration/service-registration#mesh_gateway)
|
|
parameter or an [upstream
|
|
configuration](/docs/connect/registration/service-registration#upstream-configuration-reference)
|
|
[`mesh_gateway`](/docs/connect/registration/service-registration#mesh_gateway-1)
|
|
parameter. If both are present the value defined on the upstream is used.
|
|
|
|
- `Mode` `(string: "")` - One of `none`, `local`, or `remote`.
|
|
|
|
### Sample Compilations
|
|
|
|
Full documentation for the output fields is found on the [discovery chain
|
|
internals](/docs/connect/l7-traffic/discovery-chain#compileddiscoverychain)
|
|
page.
|
|
|
|
#### Multi-Datacenter Failover
|
|
|
|
Config entries defined:
|
|
|
|
```hcl
|
|
kind = "service-resolver"
|
|
name = "web"
|
|
connect_timeout = "15s"
|
|
failover = {
|
|
"*" = {
|
|
datacenters = ["dc3", "dc4"]
|
|
}
|
|
}
|
|
```
|
|
|
|
Request:
|
|
|
|
```shell-session
|
|
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"Chain": {
|
|
"ServiceName": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"Protocol": "tcp",
|
|
"StartNode": "resolver:web.default.dc1",
|
|
"Nodes": {
|
|
"resolver:web.default.dc1": {
|
|
"Type": "resolver",
|
|
"Name": "web.default.dc1",
|
|
"Resolver": {
|
|
"ConnectTimeout": "15s",
|
|
"Target": "web.default.dc1",
|
|
"Failover": {
|
|
"Targets": ["web.default.dc3", "web.default.dc4"]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Targets": {
|
|
"web.default.dc1": {
|
|
"ID": "web.default.dc1",
|
|
"Service": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"MeshGateway": {},
|
|
"Subset": {},
|
|
"SNI": "web.default.dc1.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
|
|
"Name": "web.default.dc1.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
|
|
},
|
|
"web.default.dc3": {
|
|
"ID": "web.default.dc3",
|
|
"Service": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc3",
|
|
"MeshGateway": {},
|
|
"Subset": {},
|
|
"SNI": "web.default.dc3.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
|
|
"Name": "web.default.dc3.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
|
|
},
|
|
"web.default.dc4": {
|
|
"ID": "web.default.dc4",
|
|
"Service": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc4",
|
|
"MeshGateway": {},
|
|
"Subset": {},
|
|
"SNI": "web.default.dc4.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
|
|
"Name": "web.default.dc4.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Datacenter Redirect with Overrides
|
|
|
|
Config entries defined:
|
|
|
|
```hcl
|
|
kind = "service-resolver"
|
|
name = "web"
|
|
redirect {
|
|
datacenter = "dc2"
|
|
}
|
|
```
|
|
|
|
Request:
|
|
|
|
```shell-session
|
|
$ curl --request POST \
|
|
--data '
|
|
{
|
|
"OverrideConnectTimeout": "7s",
|
|
"OverrideProtocol": "grpc",
|
|
"OverrideMeshGateway": {
|
|
"Mode": "remote"
|
|
}
|
|
}
|
|
' http://127.0.0.1:8500/v1/discovery-chain/web
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"Chain": {
|
|
"ServiceName": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"CustomizationHash": "b94f529a",
|
|
"Protocol": "grpc",
|
|
"StartNode": "resolver:web.default.dc2",
|
|
"Nodes": {
|
|
"resolver:web.default.dc2": {
|
|
"Type": "resolver",
|
|
"Name": "web.default.dc2",
|
|
"Resolver": {
|
|
"ConnectTimeout": "7s",
|
|
"Target": "web.default.dc2"
|
|
}
|
|
}
|
|
},
|
|
"Targets": {
|
|
"web.default.dc2": {
|
|
"ID": "web.default.dc2",
|
|
"Service": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc2",
|
|
"MeshGateway": {
|
|
"Mode": "remote"
|
|
},
|
|
"Subset": {},
|
|
"SNI": "web.default.dc2.internal.59c17fd4-8dfa-f54a-ae71-855b26faf637.consul",
|
|
"Name": "web.default.dc2.internal.59c17fd4-8dfa-f54a-ae71-855b26faf637.consul"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Version Split For Alternate Datacenter
|
|
|
|
Config entries defined:
|
|
|
|
```hcl
|
|
kind = "service-resolver"
|
|
name = "web"
|
|
default_subset = "v1"
|
|
subsets = {
|
|
"v1" = {
|
|
filter = "Service.Meta.version == v1"
|
|
}
|
|
"v2" = {
|
|
filter = "Service.Meta.version == v2"
|
|
}
|
|
}
|
|
# ---------------------------
|
|
kind = "service-defaults"
|
|
name = "web"
|
|
protocol = "http"
|
|
# ---------------------------
|
|
kind = "service-splitter"
|
|
name = "web"
|
|
splits = [
|
|
{
|
|
weight = 90
|
|
service_subset = "v1"
|
|
},
|
|
{
|
|
weight = 10
|
|
service_subset = "v2"
|
|
},
|
|
]
|
|
```
|
|
|
|
Request:
|
|
|
|
```shell-session
|
|
$ curl http://127.0.0.1:8500/v1/discovery-chain/web?compile-dc=dc2
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"Chain": {
|
|
"ServiceName": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc2",
|
|
"Protocol": "http",
|
|
"StartNode": "splitter:web",
|
|
"Nodes": {
|
|
"resolver:v1.web.default.dc2": {
|
|
"Type": "resolver",
|
|
"Name": "v1.web.default.dc2",
|
|
"Resolver": {
|
|
"ConnectTimeout": "5s",
|
|
"Target": "v1.web.default.dc2"
|
|
}
|
|
},
|
|
"resolver:v2.web.default.dc2": {
|
|
"Type": "resolver",
|
|
"Name": "v2.web.default.dc2",
|
|
"Resolver": {
|
|
"ConnectTimeout": "5s",
|
|
"Target": "v2.web.default.dc2"
|
|
}
|
|
},
|
|
"splitter:web": {
|
|
"Type": "splitter",
|
|
"Name": "web",
|
|
"Splits": [
|
|
{
|
|
"Weight": 90,
|
|
"NextNode": "resolver:v1.web.default.dc2"
|
|
},
|
|
{
|
|
"Weight": 10,
|
|
"NextNode": "resolver:v2.web.default.dc2"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"Targets": {
|
|
"v1.web.default.dc2": {
|
|
"ID": "v1.web.default.dc2",
|
|
"Service": "web",
|
|
"ServiceSubset": "v1",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc2",
|
|
"MeshGateway": {},
|
|
"Subset": {
|
|
"Filter": "Service.Meta.version == v1"
|
|
},
|
|
"SNI": "v1.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul",
|
|
"Name": "v1.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul"
|
|
},
|
|
"v2.web.default.dc2": {
|
|
"ID": "v2.web.default.dc2",
|
|
"Service": "web",
|
|
"ServiceSubset": "v2",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc2",
|
|
"MeshGateway": {},
|
|
"Subset": {
|
|
"Filter": "Service.Meta.version == v2"
|
|
},
|
|
"SNI": "v2.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul",
|
|
"Name": "v2.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### HTTP Path Routing
|
|
|
|
Config entries defined:
|
|
|
|
```hcl
|
|
kind = "service-resolver"
|
|
name = "web"
|
|
subsets = {
|
|
"canary" = {
|
|
filter = "Service.Meta.flavor == canary"
|
|
}
|
|
}
|
|
# ---------------------------
|
|
kind = "proxy-defaults"
|
|
name = "web"
|
|
config {
|
|
protocol = "http"
|
|
}
|
|
# ---------------------------
|
|
kind = "service-router"
|
|
name = "web"
|
|
routes = [
|
|
{
|
|
match {
|
|
http {
|
|
path_prefix = "/admin"
|
|
}
|
|
}
|
|
destination {
|
|
service = "admin"
|
|
prefix_rewrite = "/"
|
|
request_timeout = "15s"
|
|
}
|
|
},
|
|
{
|
|
match {
|
|
http {
|
|
header = [
|
|
{
|
|
name = "x-debug"
|
|
exact = "1"
|
|
},
|
|
]
|
|
}
|
|
}
|
|
destination {
|
|
service = "web"
|
|
service_subset = "canary"
|
|
num_retries = 5
|
|
retry_on_connect_failure = true
|
|
retry_on_status_codes = [401, 409]
|
|
}
|
|
},
|
|
]
|
|
```
|
|
|
|
Request:
|
|
|
|
```shell-session
|
|
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"Chain": {
|
|
"ServiceName": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"Protocol": "http",
|
|
"StartNode": "router:web",
|
|
"Nodes": {
|
|
"resolver:admin.default.dc1": {
|
|
"Type": "resolver",
|
|
"Name": "admin.default.dc1",
|
|
"Resolver": {
|
|
"ConnectTimeout": "5s",
|
|
"Default": true,
|
|
"Target": "admin.default.dc1"
|
|
}
|
|
},
|
|
"resolver:canary.web.default.dc1": {
|
|
"Type": "resolver",
|
|
"Name": "canary.web.default.dc1",
|
|
"Resolver": {
|
|
"ConnectTimeout": "5s",
|
|
"Target": "canary.web.default.dc1"
|
|
}
|
|
},
|
|
"resolver:web.default.dc1": {
|
|
"Type": "resolver",
|
|
"Name": "web.default.dc1",
|
|
"Resolver": {
|
|
"ConnectTimeout": "5s",
|
|
"Target": "web.default.dc1"
|
|
}
|
|
},
|
|
"router:web": {
|
|
"Type": "router",
|
|
"Name": "web",
|
|
"Routes": [
|
|
{
|
|
"Definition": {
|
|
"Match": {
|
|
"HTTP": {
|
|
"PathPrefix": "/admin"
|
|
}
|
|
},
|
|
"Destination": {
|
|
"RequestTimeout": "15s",
|
|
"Service": "admin",
|
|
"PrefixRewrite": "/"
|
|
}
|
|
},
|
|
"NextNode": "resolver:admin.default.dc1"
|
|
},
|
|
{
|
|
"Definition": {
|
|
"Match": {
|
|
"HTTP": {
|
|
"Header": [
|
|
{
|
|
"Name": "x-debug",
|
|
"Exact": "1"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"Destination": {
|
|
"Service": "web",
|
|
"ServiceSubset": "canary",
|
|
"NumRetries": 5,
|
|
"RetryOnConnectFailure": true,
|
|
"RetryOnStatusCodes": [401, 409]
|
|
}
|
|
},
|
|
"NextNode": "resolver:canary.web.default.dc1"
|
|
},
|
|
{
|
|
"Definition": {
|
|
"Match": {
|
|
"HTTP": {
|
|
"PathPrefix": "/"
|
|
}
|
|
},
|
|
"Destination": {
|
|
"Service": "web"
|
|
}
|
|
},
|
|
"NextNode": "resolver:web.default.dc1"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"Targets": {
|
|
"admin.default.dc1": {
|
|
"ID": "admin.default.dc1",
|
|
"Service": "admin",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"MeshGateway": {},
|
|
"Subset": {},
|
|
"SNI": "admin.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
|
|
"Name": "admin.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
|
|
},
|
|
"canary.web.default.dc1": {
|
|
"ID": "canary.web.default.dc1",
|
|
"Service": "web",
|
|
"ServiceSubset": "canary",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"MeshGateway": {},
|
|
"Subset": {
|
|
"Filter": "Service.Meta.flavor == canary"
|
|
},
|
|
"SNI": "canary.web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
|
|
"Name": "canary.web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
|
|
},
|
|
"web.default.dc1": {
|
|
"ID": "web.default.dc1",
|
|
"Service": "web",
|
|
"Namespace": "default",
|
|
"Datacenter": "dc1",
|
|
"MeshGateway": {},
|
|
"Subset": {},
|
|
"SNI": "web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
|
|
"Name": "web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Methods to Specify Namespace <EnterpriseAlert inline />
|
|
|
|
The discovery chain endpoint
|
|
supports several methods for specifying the namespace to use as the basis of discovery chain compilation
|
|
with the following order of precedence:
|
|
1. `ns` query parameter
|
|
1. `X-Consul-Namespace` request header
|
|
1. Namespace is inherited from the namespace of the request's ACL token (if any)
|
|
1. The `default` namespace
|