2
0
mirror of https://github.com/status-im/consul.git synced 2025-01-12 14:55:02 +00:00
Matt Keeler f3d9b999ee
Add tagged addresses for services ()
This allows addresses to be tagged at the service level similar to what we allow for nodes already. The address translation that can be enabled with the `translate_wan_addrs` config was updated to take these new addresses into account as well.
2019-06-17 10:51:50 -04:00

99 lines
4.2 KiB
Go

package agent
import (
"fmt"
"github.com/hashicorp/consul/agent/structs"
)
// TranslateServicePort is used to provide the final, translated port for a service,
// depending on how the agent and the other node are configured. The dc
// parameter is the dc the datacenter this node is from.
func (a *Agent) TranslateServicePort(dc string, port int, taggedAddresses map[string]structs.ServiceAddress) int {
if a.config.TranslateWANAddrs && (a.config.Datacenter != dc) {
if wanAddr, ok := taggedAddresses["wan"]; ok && wanAddr.Port != 0 {
return wanAddr.Port
}
}
return port
}
// TranslateServiceAddress is used to provide the final, translated address for a node,
// depending on how the agent and the other node are configured. The dc
// parameter is the dc the datacenter this node is from.
func (a *Agent) TranslateServiceAddress(dc string, addr string, taggedAddresses map[string]structs.ServiceAddress) string {
if a.config.TranslateWANAddrs && (a.config.Datacenter != dc) {
if wanAddr, ok := taggedAddresses["wan"]; ok && wanAddr.Address != "" {
return wanAddr.Address
}
}
return addr
}
// TranslateAddress is used to provide the final, translated address for a node,
// depending on how the agent and the other node are configured. The dc
// parameter is the dc the datacenter this node is from.
func (a *Agent) TranslateAddress(dc string, addr string, taggedAddresses map[string]string) string {
if a.config.TranslateWANAddrs && (a.config.Datacenter != dc) {
wanAddr := taggedAddresses["wan"]
if wanAddr != "" {
addr = wanAddr
}
}
return addr
}
// TranslateAddresses translates addresses in the given structure into the
// final, translated address, depending on how the agent and the other node are
// configured. The dc parameter is the datacenter this structure is from.
func (a *Agent) TranslateAddresses(dc string, subj interface{}) {
// CAUTION - SUBTLE! An agent running on a server can, in some cases,
// return pointers directly into the immutable state store for
// performance (it's via the in-memory RPC mechanism). It's never safe
// to modify those values, so we short circuit here so that we never
// update any structures that are from our own datacenter. This works
// for address translation because we *never* need to translate local
// addresses, but this is super subtle, so we've piped all the in-place
// address translation into this function which makes sure this check is
// done. This also happens to skip looking at any of the incoming
// structure for the common case of not needing to translate, so it will
// skip a lot of work if no translation needs to be done.
if !a.config.TranslateWANAddrs || (a.config.Datacenter == dc) {
return
}
// Translate addresses in-place, subject to the condition checked above
// which ensures this is safe to do since we are operating on a local
// copy of the data.
switch v := subj.(type) {
case structs.CheckServiceNodes:
for _, entry := range v {
entry.Node.Address = a.TranslateAddress(dc, entry.Node.Address, entry.Node.TaggedAddresses)
entry.Service.Address = a.TranslateServiceAddress(dc, entry.Service.Address, entry.Service.TaggedAddresses)
entry.Service.Port = a.TranslateServicePort(dc, entry.Service.Port, entry.Service.TaggedAddresses)
}
case *structs.Node:
v.Address = a.TranslateAddress(dc, v.Address, v.TaggedAddresses)
case structs.Nodes:
for _, node := range v {
node.Address = a.TranslateAddress(dc, node.Address, node.TaggedAddresses)
}
case structs.ServiceNodes:
for _, entry := range v {
entry.Address = a.TranslateAddress(dc, entry.Address, entry.TaggedAddresses)
entry.ServiceAddress = a.TranslateServiceAddress(dc, entry.ServiceAddress, entry.ServiceTaggedAddresses)
entry.ServicePort = a.TranslateServicePort(dc, entry.ServicePort, entry.ServiceTaggedAddresses)
}
case *structs.NodeServices:
if v.Node != nil {
v.Node.Address = a.TranslateAddress(dc, v.Node.Address, v.Node.TaggedAddresses)
}
for _, entry := range v.Services {
entry.Address = a.TranslateServiceAddress(dc, entry.Address, entry.TaggedAddresses)
entry.Port = a.TranslateServicePort(dc, entry.Port, entry.TaggedAddresses)
}
default:
panic(fmt.Errorf("Unhandled type passed to address translator: %#v", subj))
}
}