Merge pull request #2280 from hashicorp/f-lan-tag
Adds missing TaggedAddress structures to Go API client, adapts for address translation.
This commit is contained in:
commit
59fa4b3ae3
12
api/api.go
12
api/api.go
|
@ -80,6 +80,9 @@ type QueryMeta struct {
|
|||
|
||||
// How long did the request take
|
||||
RequestTime time.Duration
|
||||
|
||||
// Is address translation enabled for HTTP responses on this agent
|
||||
AddressTranslationEnabled bool
|
||||
}
|
||||
|
||||
// WriteMeta is used to return meta data about a write
|
||||
|
@ -542,6 +545,15 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error {
|
|||
default:
|
||||
q.KnownLeader = false
|
||||
}
|
||||
|
||||
// Parse X-Consul-Translate-Addresses
|
||||
switch header.Get("X-Consul-Translate-Addresses") {
|
||||
case "true":
|
||||
q.AddressTranslationEnabled = true
|
||||
default:
|
||||
q.AddressTranslationEnabled = false
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -306,6 +306,7 @@ func TestParseQueryMeta(t *testing.T) {
|
|||
resp.Header.Set("X-Consul-Index", "12345")
|
||||
resp.Header.Set("X-Consul-LastContact", "80")
|
||||
resp.Header.Set("X-Consul-KnownLeader", "true")
|
||||
resp.Header.Set("X-Consul-Translate-Addresses", "true")
|
||||
|
||||
qm := &QueryMeta{}
|
||||
if err := parseQueryMeta(resp, qm); err != nil {
|
||||
|
@ -321,6 +322,9 @@ func TestParseQueryMeta(t *testing.T) {
|
|||
if !qm.KnownLeader {
|
||||
t.Fatalf("Bad: %v", qm)
|
||||
}
|
||||
if !qm.AddressTranslationEnabled {
|
||||
t.Fatalf("Bad: %v", qm)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPI_UnixSocket(t *testing.T) {
|
||||
|
|
|
@ -3,11 +3,13 @@ package api
|
|||
type Node struct {
|
||||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
}
|
||||
|
||||
type CatalogService struct {
|
||||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
ServiceID string
|
||||
ServiceName string
|
||||
ServiceAddress string
|
||||
|
@ -24,6 +26,7 @@ type CatalogNode struct {
|
|||
type CatalogRegistration struct {
|
||||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
Datacenter string
|
||||
Service *AgentService
|
||||
Check *AgentCheck
|
||||
|
|
|
@ -51,6 +51,10 @@ func TestCatalog_Nodes(t *testing.T) {
|
|||
return false, fmt.Errorf("Bad: %v", nodes)
|
||||
}
|
||||
|
||||
if _, ok := nodes[0].TaggedAddresses["wan"]; !ok {
|
||||
return false, fmt.Errorf("Bad: %v", nodes)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -128,10 +132,15 @@ func TestCatalog_Node(t *testing.T) {
|
|||
if meta.LastIndex == 0 {
|
||||
return false, fmt.Errorf("Bad: %v", meta)
|
||||
}
|
||||
|
||||
if len(info.Services) == 0 {
|
||||
return false, fmt.Errorf("Bad: %v", info)
|
||||
}
|
||||
|
||||
if _, ok := info.Node.TaggedAddresses["wan"]; !ok {
|
||||
return false, fmt.Errorf("Bad: %v", info)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -94,6 +94,9 @@ func TestHealth_Service(t *testing.T) {
|
|||
if len(checks) == 0 {
|
||||
return false, fmt.Errorf("Bad: %v", checks)
|
||||
}
|
||||
if _, ok := checks[0].Node.TaggedAddresses["wan"]; !ok {
|
||||
return false, fmt.Errorf("Bad: %v", checks)
|
||||
}
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -17,6 +17,9 @@ func TestPreparedQuery(t *testing.T) {
|
|||
Datacenter: "dc1",
|
||||
Node: "foobar",
|
||||
Address: "192.168.10.10",
|
||||
TaggedAddresses: map[string]string{
|
||||
"wan": "127.0.0.1",
|
||||
},
|
||||
Service: &AgentService{
|
||||
ID: "redis1",
|
||||
Service: "redis",
|
||||
|
@ -96,6 +99,9 @@ func TestPreparedQuery(t *testing.T) {
|
|||
if len(results.Nodes) != 1 || results.Nodes[0].Node.Node != "foobar" {
|
||||
t.Fatalf("bad: %v", results)
|
||||
}
|
||||
if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" {
|
||||
t.Fatalf("bad: %v", results)
|
||||
}
|
||||
|
||||
// Execute by name.
|
||||
results, _, err = query.Execute("my-query", nil)
|
||||
|
@ -105,6 +111,9 @@ func TestPreparedQuery(t *testing.T) {
|
|||
if len(results.Nodes) != 1 || results.Nodes[0].Node.Node != "foobar" {
|
||||
t.Fatalf("bad: %v", results)
|
||||
}
|
||||
if wan, ok := results.Nodes[0].Node.TaggedAddresses["wan"]; !ok || wan != "127.0.0.1" {
|
||||
t.Fatalf("bad: %v", results)
|
||||
}
|
||||
|
||||
// Delete it.
|
||||
_, err = query.Delete(def.ID, nil)
|
||||
|
|
|
@ -170,6 +170,7 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
|
|||
|
||||
// Create the default set of tagged addresses.
|
||||
config.TaggedAddresses = map[string]string{
|
||||
"lan": config.AdvertiseAddr,
|
||||
"wan": config.AdvertiseAddrWan,
|
||||
}
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ func TestAgent_CheckAdvertiseAddrsSettings(t *testing.T) {
|
|||
t.Fatalf("RPC is not properly set to %v: %s", c.AdvertiseAddrs.RPC, rpc)
|
||||
}
|
||||
expected := map[string]string{
|
||||
"lan": agent.config.AdvertiseAddr,
|
||||
"wan": agent.config.AdvertiseAddrWan,
|
||||
}
|
||||
if !reflect.DeepEqual(agent.config.TaggedAddresses, expected) {
|
||||
|
|
|
@ -329,6 +329,7 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) {
|
|||
func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Request) (interface{}, error)) func(resp http.ResponseWriter, req *http.Request) {
|
||||
f := func(resp http.ResponseWriter, req *http.Request) {
|
||||
setHeaders(resp, s.agent.config.HTTPAPIResponseHeaders)
|
||||
setTranslateAddr(resp, s.agent.config.TranslateWanAddrs)
|
||||
|
||||
// Obfuscate any tokens from appearing in the logs
|
||||
formVals, err := url.ParseQuery(req.URL.RawQuery)
|
||||
|
@ -373,6 +374,7 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
|
|||
if strings.Contains(errMsg, "Permission denied") || strings.Contains(errMsg, "ACL not found") {
|
||||
code = http.StatusForbidden // 403
|
||||
}
|
||||
|
||||
resp.WriteHeader(code)
|
||||
resp.Write([]byte(err.Error()))
|
||||
return
|
||||
|
@ -452,6 +454,14 @@ func decodeBody(req *http.Request, out interface{}, cb func(interface{}) error)
|
|||
return mapstructure.Decode(raw, out)
|
||||
}
|
||||
|
||||
// setTranslateAddr is used to set the address translation header. This is only
|
||||
// present if the feature is active.
|
||||
func setTranslateAddr(resp http.ResponseWriter, active bool) {
|
||||
if active {
|
||||
resp.Header().Set("X-Consul-Translate-Addresses", "true")
|
||||
}
|
||||
}
|
||||
|
||||
// setIndex is used to set the index response header
|
||||
func setIndex(resp http.ResponseWriter, index uint64) {
|
||||
resp.Header().Set("X-Consul-Index", strconv.FormatUint(index, 10))
|
||||
|
|
|
@ -223,6 +223,51 @@ func TestSetMeta(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestHTTPAPI_TranslateAddrHeader(t *testing.T) {
|
||||
// Header should not be present if address translation is off.
|
||||
{
|
||||
dir, srv := makeHTTPServer(t)
|
||||
defer os.RemoveAll(dir)
|
||||
defer srv.Shutdown()
|
||||
defer srv.agent.Shutdown()
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", "/v1/agent/self", nil)
|
||||
srv.wrap(handler)(resp, req)
|
||||
|
||||
translate := resp.Header().Get("X-Consul-Translate-Addresses")
|
||||
if translate != "" {
|
||||
t.Fatalf("bad: expected %q, got %q", "", translate)
|
||||
}
|
||||
}
|
||||
|
||||
// Header should be set to true if it's turned on.
|
||||
{
|
||||
dir, srv := makeHTTPServer(t)
|
||||
srv.agent.config.TranslateWanAddrs = true
|
||||
defer os.RemoveAll(dir)
|
||||
defer srv.Shutdown()
|
||||
defer srv.agent.Shutdown()
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
req, _ := http.NewRequest("GET", "/v1/agent/self", nil)
|
||||
srv.wrap(handler)(resp, req)
|
||||
|
||||
translate := resp.Header().Get("X-Consul-Translate-Addresses")
|
||||
if translate != "true" {
|
||||
t.Fatalf("bad: expected %q, got %q", "true", translate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAPIResponseHeaders(t *testing.T) {
|
||||
dir, srv := makeHTTPServer(t)
|
||||
srv.agent.config.HTTPAPIResponseHeaders = map[string]string{
|
||||
|
|
|
@ -96,3 +96,12 @@ configuration option. However, the token can also be specified per-request
|
|||
by using the `X-Consul-Token` request header or the `token` querystring
|
||||
parameter. The request header takes precedence over the default token, and
|
||||
the querystring parameter takes precedence over everything.
|
||||
|
||||
|
||||
## <a id="translate_header"></a>Translated Addresses
|
||||
|
||||
Consul 0.7 added the ability to translate addresses in HTTP response based on the configuration
|
||||
setting for [`translate_wan_addrs`](/docs/agent/options.html#translate_wan_addrs). In order to
|
||||
allow clients to know if address translation is in effect, the `X-Consul-Translate-Addresses`
|
||||
header will be added if translation is enabled, and will have a value of `true`. If translation
|
||||
is not enabled then this header will not be present.
|
||||
|
|
|
@ -41,7 +41,8 @@ body must look something like:
|
|||
"Node": "foobar",
|
||||
"Address": "192.168.10.10",
|
||||
"TaggedAddresses": {
|
||||
"wan": "127.0.0.1"
|
||||
"lan": "192.168.10.10",
|
||||
"wan": "10.0.10.10"
|
||||
},
|
||||
"Service": {
|
||||
"ID": "redis1",
|
||||
|
@ -69,7 +70,8 @@ requires `Node` and `Address` to be provided while `Datacenter` will be defaulte
|
|||
to match that of the agent. If only those are provided, the endpoint will register
|
||||
the node with the catalog. `TaggedAddresses` can be used in conjunction with the
|
||||
[`translate_wan_addrs`](/docs/agent/options.html#translate_wan_addrs) configuration
|
||||
option. Currently only the "wan" tag is supported.
|
||||
option and the "wan" address. The "lan" address was added in Consul 0.7 to help find
|
||||
the LAN address if address translation is enabled.
|
||||
|
||||
If the `Service` key is provided, the service will also be registered. If
|
||||
`ID` is not provided, it will be defaulted to the value of the `Service.Service` property.
|
||||
|
@ -200,6 +202,7 @@ It returns a JSON body like this:
|
|||
"Node": "baz",
|
||||
"Address": "10.1.10.11",
|
||||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.11",
|
||||
"wan": "10.1.10.11"
|
||||
}
|
||||
},
|
||||
|
@ -207,6 +210,7 @@ It returns a JSON body like this:
|
|||
"Node": "foobar",
|
||||
"Address": "10.1.10.12",
|
||||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.11",
|
||||
"wan": "10.1.10.12"
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +291,7 @@ It returns a JSON body like this:
|
|||
"Node": "foobar",
|
||||
"Address": "10.1.10.12",
|
||||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.12",
|
||||
"wan": "10.1.10.12"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -129,6 +129,7 @@ It returns a JSON body like this:
|
|||
"Node": "foobar",
|
||||
"Address": "10.1.10.12",
|
||||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.12",
|
||||
"wan": "10.1.10.12"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -399,7 +399,11 @@ a JSON body will be returned like this:
|
|||
{
|
||||
"Node": {
|
||||
"Node": "foobar",
|
||||
"Address": "10.1.10.12"
|
||||
"Address": "10.1.10.12",
|
||||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.12",
|
||||
"wan": "10.1.10.12"
|
||||
}
|
||||
},
|
||||
"Service": {
|
||||
"ID": "redis",
|
||||
|
|
|
@ -756,9 +756,14 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
|
|||
default.
|
||||
<br>
|
||||
<br>
|
||||
Starting in Consul 0.7 and later, node addresses in responses to the following HTTP endpoints will
|
||||
prefer a node's configured <a href="#_advertise-wan">WAN address</a> when querying for a node in a
|
||||
remote datacenter:
|
||||
Starting in Consul 0.7 and later, node addresses in responses to HTTP requests will also prefer a
|
||||
node's configured <a href="#_advertise-wan">WAN address</a> when querying for a node in a remote
|
||||
datacenter. An [`X-Consul-Translate-Addresses`](/docs/agent/http.html#translate_header) header
|
||||
will be present on all responses when translation is enabled to help clients know that the addresses
|
||||
may be translated. The `TaggedAddresses` field in responses also have a `lan` address for clients that
|
||||
need knowledge of that address, regardless of translation.
|
||||
<br>
|
||||
<br>The following endpoints translate addresses:
|
||||
<br>
|
||||
* [`/v1/catalog/nodes`](/docs/agent/http/catalog.html#catalog_nodes)
|
||||
* [`/v1/catalog/node/<node>`](/docs/agent/http/catalog.html#catalog_node)
|
||||
|
|
Loading…
Reference in New Issue