Skip to content

Commit

Permalink
consul: manual backport of faac908 (#14958)
Browse files Browse the repository at this point in the history
Co-authored-by: temp <temp@hashicorp.com>
  • Loading branch information
hc-github-team-nomad-core and temp authored Oct 19, 2022
1 parent 67f3a31 commit f5a5d91
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 28 deletions.
36 changes: 35 additions & 1 deletion command/agent/consul/catalog_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ func (c *MockAgent) CheckRegs() []*api.AgentCheckRegistration {
func (c *MockAgent) CheckRegister(check *api.AgentCheckRegistration) error {
c.mu.Lock()
defer c.mu.Unlock()
return c.checkRegister(check)
}

// checkRegister registers a check; c.mu must be held.
func (c *MockAgent) checkRegister(check *api.AgentCheckRegistration) error {
c.hits++

// Consul will set empty Namespace to default, do the same here
Expand All @@ -275,14 +280,29 @@ func (c *MockAgent) CheckRegister(check *api.AgentCheckRegistration) error {
if c.checks[check.Namespace] == nil {
c.checks[check.Namespace] = make(map[string]*api.AgentCheckRegistration)
}

c.checks[check.Namespace][check.ID] = check

// Be nice and make checks reachable-by-service
serviceCheck := check.AgentServiceCheck

if c.services[check.Namespace] == nil {
c.services[check.Namespace] = make(map[string]*api.AgentServiceRegistration)
}
c.services[check.Namespace][check.ServiceID].Checks = append(c.services[check.Namespace][check.ServiceID].Checks, &serviceCheck)

// replace existing check if one with same id already exists
replace := false
for i := 0; i < len(c.services[check.Namespace][check.ServiceID].Checks); i++ {
if c.services[check.Namespace][check.ServiceID].Checks[i].CheckID == check.CheckID {
c.services[check.Namespace][check.ServiceID].Checks[i] = &check.AgentServiceCheck
replace = true
break
}
}

if !replace {
c.services[check.Namespace][check.ServiceID].Checks = append(c.services[check.Namespace][check.ServiceID].Checks, &serviceCheck)
}
return nil
}

Expand Down Expand Up @@ -315,6 +335,20 @@ func (c *MockAgent) ServiceRegister(service *api.AgentServiceRegistration) error
c.services[service.Namespace] = make(map[string]*api.AgentServiceRegistration)
}
c.services[service.Namespace][service.ID] = service

// as of Nomad v1.4.x registering service now also registers its checks
for _, check := range service.Checks {
if err := c.checkRegister(&api.AgentCheckRegistration{
ID: check.CheckID,
Name: check.Name,
ServiceID: service.ID,
AgentServiceCheck: *check,
Namespace: service.Namespace,
}); err != nil {
return err
}
}

return nil
}

Expand Down
46 changes: 43 additions & 3 deletions command/agent/consul/service_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,22 @@ func maybeTweakTags(wanted *api.AgentServiceRegistration, existing *api.AgentSer
}
}

// maybeTweakTaggedAddresses will remove the .TaggedAddresses fields from existing
// if wanted represents a Nomad agent (Client or Server). We do this because Consul
// sets the TaggedAddress on these legacy registrations for us
// maybeTweakTaggedAddresses will remove the Consul-injected .TaggedAddresses fields
// from existing if wanted represents a Nomad agent (Client or Server) or Nomad managed
// service, which do not themselves configure those tagged addresses. We do this
// because Consul will magically set the .TaggedAddress to values Nomad does not
// know about if they are submitted as unset.
func maybeTweakTaggedAddresses(wanted *api.AgentServiceRegistration, existing *api.AgentService) {
if isNomadAgent(wanted.ID) && len(wanted.TaggedAddresses) == 0 {
existing.TaggedAddresses = nil
if isNomadAgent(wanted.ID) || isNomadService(wanted.ID) {
if _, exists := wanted.TaggedAddresses["lan_ipv4"]; !exists {
delete(existing.TaggedAddresses, "lan_ipv4")
}
if _, exists := wanted.TaggedAddresses["wan_ipv4"]; !exists {
delete(existing.TaggedAddresses, "wan_ipv4")
}
}
}
}

Expand Down Expand Up @@ -1165,6 +1175,7 @@ func (c *ServiceClient) serviceRegs(ops *operations, service *structs.Service, w
Meta: meta,
Connect: connect, // will be nil if no Connect stanza
Proxy: gateway, // will be nil if no Connect Gateway stanza
Checks: make([]*api.AgentServiceCheck, 0, len(service.Checks)),
}
ops.regServices = append(ops.regServices, serviceReg)

Expand All @@ -1176,11 +1187,40 @@ func (c *ServiceClient) serviceRegs(ops *operations, service *structs.Service, w
for _, registration := range checkRegs {
sreg.checkIDs[registration.ID] = struct{}{}
ops.regChecks = append(ops.regChecks, registration)
serviceReg.Checks = append(
serviceReg.Checks,
apiCheckRegistrationToCheck(registration),
)
}

return sreg, nil
}

// apiCheckRegistrationToCheck converts a check registration to a check, so that
// we can include them in the initial service registration. It is expected the
// Nomad-conversion (e.g. turning script checks into ttl checks) has already been
// applied.
func apiCheckRegistrationToCheck(r *api.AgentCheckRegistration) *api.AgentServiceCheck {
return &api.AgentServiceCheck{
CheckID: r.ID,
Name: r.Name,
Interval: r.Interval,
Timeout: r.Timeout,
TTL: r.TTL,
HTTP: r.HTTP,
Header: maps.Clone(r.Header),
Method: r.Method,
Body: r.Body,
TCP: r.TCP,
Status: r.Status,
TLSSkipVerify: r.TLSSkipVerify,
GRPC: r.GRPC,
GRPCUseTLS: r.GRPCUseTLS,
SuccessBeforePassing: r.SuccessBeforePassing,
FailuresBeforeCritical: r.FailuresBeforeCritical,
}
}

// checkRegs creates check registrations for the given service
func (c *ServiceClient) checkRegs(serviceID string, service *structs.Service,
workload *WorkloadServices, sreg *ServiceRegistration) ([]*api.AgentCheckRegistration, error) {
Expand Down
42 changes: 18 additions & 24 deletions command/agent/consul/unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/plugins/drivers"
"github.com/kr/pretty"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -1730,17 +1731,13 @@ func TestGetAddress(t *testing.T) {

func TestConsul_ServiceName_Duplicates(t *testing.T) {
ci.Parallel(t)

ctx := setupFake(t)
require := require.New(t)

ctx.Workload.Services = []*structs.Service{
{
Name: "best-service",
PortLabel: "x",
Tags: []string{
"foo",
},
Tags: []string{"foo"},
Checks: []*structs.ServiceCheck{
{
Name: "check-a",
Expand All @@ -1753,12 +1750,10 @@ func TestConsul_ServiceName_Duplicates(t *testing.T) {
{
Name: "best-service",
PortLabel: "y",
Tags: []string{
"bar",
},
Tags: []string{"bar"},
Checks: []*structs.ServiceCheck{
{
Name: "checky-mccheckface",
Name: "check-b",
Type: "tcp",
Interval: time.Second,
Timeout: time.Second,
Expand All @@ -1771,21 +1766,20 @@ func TestConsul_ServiceName_Duplicates(t *testing.T) {
},
}

require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))

require.NoError(ctx.syncOnce(syncNewOps))

require.Len(ctx.FakeConsul.services["default"], 3)

for _, v := range ctx.FakeConsul.services["default"] {
if v.Name == ctx.Workload.Services[0].Name && v.Port == xPort {
require.ElementsMatch(v.Tags, ctx.Workload.Services[0].Tags)
require.Len(v.Checks, 1)
} else if v.Name == ctx.Workload.Services[1].Name && v.Port == yPort {
require.ElementsMatch(v.Tags, ctx.Workload.Services[1].Tags)
require.Len(v.Checks, 1)
} else if v.Name == ctx.Workload.Services[2].Name {
require.Len(v.Checks, 0)
must.NoError(t, ctx.ServiceClient.RegisterWorkload(ctx.Workload))
must.NoError(t, ctx.syncOnce(syncNewOps))
must.MapLen(t, 3, ctx.FakeConsul.services["default"])

for _, s := range ctx.FakeConsul.services["default"] {
switch {
case s.Name == "best-service" && s.Port == xPort:
must.SliceContainsAll(t, s.Tags, ctx.Workload.Services[0].Tags)
must.SliceLen(t, 1, s.Checks)
case s.Name == "best-service" && s.Port == yPort:
must.SliceContainsAll(t, s.Tags, ctx.Workload.Services[1].Tags)
must.SliceLen(t, 1, s.Checks)
case s.Name == "worst-service":
must.SliceEmpty(t, s.Checks)
}
}
}
Expand Down

0 comments on commit f5a5d91

Please sign in to comment.