» Discovery Chain HTTP Endpoint

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.

» 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"]
  }
}

Request:

$ 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"
            }
        }
    }
}

» Datacenter Redirect with Overrides

Config entries defined:

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

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"
            }
        }
    }
}

» 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"
  },
]

Request:

$ 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"
            }
        }
    }
}

» 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]
    }
  },
]

Request:

$ 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"
            }
        }
    }
}