diff --git a/agent/local/state.go b/agent/local/state.go index 335721a5c..f6e396131 100644 --- a/agent/local/state.go +++ b/agent/local/state.go @@ -305,6 +305,8 @@ func (l *State) removeServiceLocked(id structs.ServiceID) error { close(s.WatchCh) s.WatchCh = nil } + + l.notifyIfAliased(id) l.TriggerSyncChanges() l.broadcastUpdateLocked() @@ -379,6 +381,11 @@ func (l *State) setServiceStateLocked(s *ServiceState) { if hasOld && old.WatchCh != nil { close(old.WatchCh) } + if !hasOld { + // The status of an alias check is updated if the alias service is added/removed + // Only try notify alias checks if service didn't already exist (!hasOld) + l.notifyIfAliased(key) + } l.TriggerSyncChanges() l.broadcastUpdateLocked() @@ -1353,7 +1360,7 @@ func (l *State) syncNodeInfo() error { } } -// notifyIfAliased will notify waiters if this is a check for an aliased service +// notifyIfAliased will notify waiters of changes to an aliased service func (l *State) notifyIfAliased(serviceID structs.ServiceID) { if aliases, ok := l.checkAliases[serviceID]; ok && len(aliases) > 0 { for _, notifyCh := range aliases { diff --git a/agent/local/state_test.go b/agent/local/state_test.go index c418bb948..4a9b7f8e7 100644 --- a/agent/local/state_test.go +++ b/agent/local/state_test.go @@ -1912,6 +1912,59 @@ func TestAgent_AliasCheck(t *testing.T) { } } +func TestAgent_AliasCheck_ServiceNotification(t *testing.T) { + t.Parallel() + + require := require.New(t) + cfg := config.DefaultRuntimeConfig(`bind_addr = "127.0.0.1" data_dir = "dummy"`) + l := local.NewState(agent.LocalConfig(cfg), nil, new(token.Store)) + l.TriggerSyncChanges = func() {} + + // Add an alias check for service s1 + notifyCh := make(chan struct{}, 1) + require.NoError(l.AddAliasCheck(structs.NewCheckID(types.CheckID("a1"), nil), structs.NewServiceID("s1", nil), notifyCh)) + + // Add aliased service, s1, and verify we get notified + require.NoError(l.AddService(&structs.NodeService{Service: "s1"}, "")) + select { + case <-notifyCh: + default: + t.Fatal("notify not received") + } + + // Re-adding same service should not lead to a notification + require.NoError(l.AddService(&structs.NodeService{Service: "s1"}, "")) + select { + case <-notifyCh: + t.Fatal("notify received") + default: + } + + // Add different service and verify we do not get notified + require.NoError(l.AddService(&structs.NodeService{Service: "s2"}, "")) + select { + case <-notifyCh: + t.Fatal("notify received") + default: + } + + // Delete service and verify we get notified + require.NoError(l.RemoveService(structs.NewServiceID("s1", nil))) + select { + case <-notifyCh: + default: + t.Fatal("notify not received") + } + + // Delete different service and verify we do not get notified + require.NoError(l.RemoveService(structs.NewServiceID("s2", nil))) + select { + case <-notifyCh: + t.Fatal("notify received") + default: + } +} + func TestAgent_sendCoordinate(t *testing.T) { t.Parallel() a := agent.StartTestAgent(t, agent.TestAgent{Overrides: `