1.6.0+: The discovery chain API is available in Consul versions 1.6.0 and newer.
»Discovery Chain HTTP Endpoint
This is a low-level API primarily targeted at developers building external
Connect proxy integrations. Future
high-level proxy integration APIs may obviate the need for this API over time.
The /discovery-chain endpoint returns the compiled discovery
chain for a service.
This will fetch all related configuration
entries and render them into a form suitable
for use by a connect proxy implementation. This
is a key component of L7 Traffic
Management.
»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 |
application/json |
POST1
|
/discovery-chain/:service |
application/json |
1 Both GET and POST are for read operations. GET requests do not permit request bodies so a POST is required if override parameters are needed.
The table below shows this endpoint's support for
blocking queries,
consistency modes,
agent caching, and
required ACLs.
| Blocking Queries |
Consistency Modes |
Agent Caching |
ACL Required |
YES |
all |
background refresh |
service:read |
»URL Parameters
-
service (string: <required>) - Specifies the service to query when
compiling the discovery chain. This is provided as part of the URL.
-
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 is specified as part of the URL as a query parameter.
This value comes from an upstream
configuration
datacenter
parameter.
-
ns (string: "")
Enterprise
- Specifies the source namespace
to use as the basis of compilation. This value can be specified as the ns
URL query parameter or the X-Consul-Namespace header. If not provided by either,
the namespace will be inherited from the request's ACL token or will default
to the default namespace. Added in Consul 1.7.0.
»POST Body Parameters
»Sample Compilations
Full documentation for the output fields is found on the discovery chain
internals
page.
»Multi-Datacenter Failover
Config entries defined:
kind = "service-resolver"
name = "web"
connect_timeout = "15s"
failover = {
"*" = {
datacenters = ["dc3", "dc4"]
}
}
kind = "service-resolver"name = "web"connect_timeout = "15s"failover = { "*" = { datacenters = ["dc3", "dc4"] }}
Request:
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
Response:
{
"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"
}
}
}
}
{ "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:
kind = "service-resolver"
name = "web"
redirect {
datacenter = "dc2"
}
kind = "service-resolver"name = "web"redirect { datacenter = "dc2"}
Request:
$ curl -X POST \
-d'
{
"OverrideConnectTimeout": "7s",
"OverrideProtocol": "grpc",
"OverrideMeshGateway": {
"Mode": "remote"
}
}
' http://127.0.0.1:8500/v1/discovery-chain/web
$ curl -X POST \ -d'{ "OverrideConnectTimeout": "7s", "OverrideProtocol": "grpc", "OverrideMeshGateway": { "Mode": "remote" }}' http://127.0.0.1:8500/v1/discovery-chain/web
Response:
{
"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"
}
}
}
}
{ "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:
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"
},
]
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:
$ curl http://127.0.0.1:8500/v1/discovery-chain/web?compile-dc=dc2
$ curl http://127.0.0.1:8500/v1/discovery-chain/web?compile-dc=dc2
Response:
{
"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"
}
}
}
}
{ "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:
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]
}
},
]
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:
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
$ curl http://127.0.0.1:8500/v1/discovery-chain/web
Response:
{
"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"
}
}
}
}
{ "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" } } }}