Allow setting tagged addresses on services

This commit is contained in:
Jorge Marey 2022-05-11 18:10:53 +02:00 committed by Seth Hoenig
parent 59a4a19a4f
commit f966614602
6 changed files with 71 additions and 0 deletions

View File

@ -236,6 +236,7 @@ type Service struct {
Connect *ConsulConnect `hcl:"connect,block"`
Meta map[string]string `hcl:"meta,block"`
CanaryMeta map[string]string `hcl:"canary_meta,block"`
TaggedAddresses map[string]string `hcl:"tagged_addresses,block"`
TaskName string `mapstructure:"task" hcl:"task,optional"`
OnUpdate string `mapstructure:"on_update" hcl:"on_update,optional"`

View File

@ -41,6 +41,7 @@ func InterpolateServices(taskEnv *TaskEnv, services []*structs.Service) []*struc
service.CanaryTags = taskEnv.ParseAndReplace(service.CanaryTags)
service.Meta = interpolateMapStringString(taskEnv, service.Meta)
service.CanaryMeta = interpolateMapStringString(taskEnv, service.CanaryMeta)
service.TaggedAddresses = interpolateMapStringString(taskEnv, service.TaggedAddresses)
interpolateConnect(taskEnv, service.Connect)
interpolated[i] = service

View File

@ -213,6 +213,8 @@ func different(wanted *api.AgentServiceRegistration, existing *api.AgentService,
return true
case !reflect.DeepEqual(wanted.Meta, existing.Meta):
return true
case !reflect.DeepEqual(wanted.TaggedAddresses, existing.TaggedAddresses):
return true
case tagsDifferent(wanted.Tags, existing.Tags):
return true
case connectSidecarDifferent(wanted, sidecar):
@ -1027,6 +1029,19 @@ func (c *ServiceClient) serviceRegs(
}
}
var taggedAddresses map[string]api.ServiceAddress
for k, v := range service.TaggedAddresses {
sa, err := parseAddress(v, port)
if err != nil {
c.logger.Warn("failed to parse advertise address", "name", k, "adrress", v)
continue
}
if taggedAddresses == nil {
taggedAddresses = make(map[string]api.ServiceAddress)
}
taggedAddresses[k] = sa
}
// Build the Consul Service registration request
serviceReg := &api.AgentServiceRegistration{
Kind: kind,
@ -1038,6 +1053,7 @@ func (c *ServiceClient) serviceRegs(
Address: ip,
Port: port,
Meta: meta,
TaggedAddresses: taggedAddresses,
Connect: connect, // will be nil if no Connect stanza
Proxy: gateway, // will be nil if no Connect Gateway stanza
}
@ -1664,3 +1680,31 @@ func getNomadSidecar(id string, services map[string]*api.AgentService) *api.Agen
sidecarID := id + sidecarSuffix
return services[sidecarID]
}
func parseAddress(raw string, port int) (api.ServiceAddress, error) {
result := api.ServiceAddress{}
addr, portStr, err := net.SplitHostPort(raw)
// Error message from Go's net/ipsock.go
if err != nil {
if !strings.Contains(err.Error(), "missing port in address") {
return result, fmt.Errorf("error parsing address %q: %v", raw, err)
}
// Use the whole input as the address if there wasn't a port.
if ip := net.ParseIP(raw); ip == nil {
return result, fmt.Errorf("error parsing address %q: not an IP address", raw)
}
addr = raw
}
if portStr != "" {
port, err = strconv.Atoi(portStr)
if err != nil {
return result, fmt.Errorf("error parsing port %q: %v", portStr, err)
}
}
result.Address = addr
result.Port = port
return result, nil
}

View File

@ -1376,6 +1376,7 @@ func ApiServicesToStructs(in []*api.Service, group bool) []*structs.Service {
Address: s.Address,
Meta: helper.CopyMapStringString(s.Meta),
CanaryMeta: helper.CopyMapStringString(s.CanaryMeta),
TaggedAddresses: helper.CopyMapStringString(s.TaggedAddresses),
OnUpdate: s.OnUpdate,
Provider: s.Provider,
}

View File

@ -50,6 +50,7 @@ func parseService(o *ast.ObjectItem) (*api.Service, error) {
"task",
"meta",
"canary_meta",
"tagged_addresses",
"on_update",
"provider",
}
@ -68,6 +69,7 @@ func parseService(o *ast.ObjectItem) (*api.Service, error) {
delete(m, "connect")
delete(m, "meta")
delete(m, "canary_meta")
delete(m, "tagged_addresses")
if err := mapstructure.WeakDecode(m, &service); err != nil {
return nil, err
@ -140,6 +142,20 @@ func parseService(o *ast.ObjectItem) (*api.Service, error) {
}
}
// Parse out tagged_addresses fields. These are in HCL as a list so we need
// to iterate over them and merge them.
if taO := listVal.Filter("tagged_addresses"); len(taO.Items) > 0 {
for _, o := range taO.Elem().Items {
var m map[string]interface{}
if err := hcl.DecodeObject(&m, o.Val); err != nil {
return nil, err
}
if err := mapstructure.WeakDecode(m, &service.TaggedAddresses); err != nil {
return nil, err
}
}
}
return &service, nil
}

View File

@ -472,6 +472,8 @@ type Service struct {
Meta map[string]string // Consul service meta
CanaryMeta map[string]string // Consul service meta when it is a canary
TaggedAddresses map[string]string
// The consul namespace in which this service will be registered. Namespace
// at the service.check level is not part of the Nomad API - it must be
// set at the job or group level. This field is managed internally so
@ -516,6 +518,7 @@ func (s *Service) Copy() *Service {
ns.Meta = helper.CopyMapStringString(s.Meta)
ns.CanaryMeta = helper.CopyMapStringString(s.CanaryMeta)
ns.TaggedAddresses = helper.CopyMapStringString(s.TaggedAddresses)
return ns
}
@ -699,6 +702,7 @@ func (s *Service) Hash(allocID, taskName string, canary bool) string {
hashBool(h, s.EnableTagOverride, "ETO")
hashMeta(h, s.Meta)
hashMeta(h, s.CanaryMeta)
hashMeta(h, s.TaggedAddresses)
hashConnect(h, s.Connect)
hashString(h, s.OnUpdate)
hashString(h, s.Namespace)
@ -825,6 +829,10 @@ OUTER:
return false
}
if !reflect.DeepEqual(s.TaggedAddresses, o.TaggedAddresses) {
return false
}
if !helper.CompareSliceSetString(s.Tags, o.Tags) {
return false
}