Skip to content

Commit

Permalink
Allow setting tagged addresses on services
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgemarey committed May 11, 2022
1 parent 894c2e6 commit 71b8f18
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`

Expand Down
1 change: 1 addition & 0 deletions client/taskenv/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions command/agent/consul/service_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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,
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
1 change: 1 addition & 0 deletions command/agent/job_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
16 changes: 16 additions & 0 deletions jobspec/parse_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func parseService(o *ast.ObjectItem) (*api.Service, error) {
"task",
"meta",
"canary_meta",
"tagged_addresses",
"on_update",
"provider",
}
Expand All @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
8 changes: 8 additions & 0 deletions nomad/structs/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -824,6 +828,10 @@ OUTER:
return false
}

if !reflect.DeepEqual(s.TaggedAddresses, o.TaggedAddresses) {
return false
}

if !helper.CompareSliceSetString(s.Tags, o.Tags) {
return false
}
Expand Down

0 comments on commit 71b8f18

Please sign in to comment.