diff --git a/command/agent/agent.go b/command/agent/agent.go index 418c5fef4c..35429b4409 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -114,6 +114,14 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) { if config.Server { err = agent.setupServer() agent.state.SetIface(agent.server) + + // Automatically register the "consul" service on server nodes + consulService := structs.NodeService{ + Service: consul.ConsulServiceName, + ID: consul.ConsulServiceID, + Port: agent.config.Ports.Server, + } + agent.state.AddService(&consulService) } else { err = agent.setupClient() agent.state.SetIface(agent.client) @@ -452,6 +460,13 @@ func (a *Agent) AddService(service *structs.NodeService, chkType *CheckType) err // RemoveService is used to remove a service entry. // The agent will make a best effort to ensure it is deregistered func (a *Agent) RemoveService(serviceID string) error { + // Protect "consul" service from deletion by a user + if a.server != nil && serviceID == consul.ConsulServiceID { + return fmt.Errorf( + "Deregistering the %s service is not allowed", + consul.ConsulServiceID) + } + // Remove service immeidately a.state.RemoveService(serviceID) diff --git a/command/agent/agent_endpoint_test.go b/command/agent/agent_endpoint_test.go index 73682a9cc4..798fd4a1db 100644 --- a/command/agent/agent_endpoint_test.go +++ b/command/agent/agent_endpoint_test.go @@ -31,7 +31,7 @@ func TestHTTPAgentServices(t *testing.T) { t.Fatalf("Err: %v", err) } val := obj.(map[string]*structs.NodeService) - if len(val) != 1 { + if len(val) != 2 { t.Fatalf("bad services: %v", obj) } if val["mysql"].Port != 5000 { diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index 3343c4afc1..64ae5c873e 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -146,6 +146,11 @@ func TestAgent_RemoveService(t *testing.T) { t.Fatalf("err: %v", err) } + // Remove the consul service + if err := agent.RemoveService("consul"); err == nil { + t.Fatalf("should have errored") + } + srv := &structs.NodeService{ ID: "redis", Service: "redis", @@ -315,3 +320,14 @@ func TestAgent_UpdateCheck(t *testing.T) { t.Fatalf("bad: %v", status) } } + +func TestAgent_ConsulService(t *testing.T) { + dir, agent := makeAgent(t, nextConfig()) + defer os.RemoveAll(dir) + defer agent.Shutdown() + + services := agent.state.Services() + if _, ok := services[consul.ConsulServiceID]; !ok { + t.Fatalf("%s service should be registered", consul.ConsulServiceID) + } +} diff --git a/command/agent/local.go b/command/agent/local.go index b35e86e847..86b7e45ff2 100644 --- a/command/agent/local.go +++ b/command/agent/local.go @@ -314,11 +314,6 @@ func (l *localState) setSyncState() error { // If we don't have the service locally, deregister it existing, ok := l.services[id] if !ok { - // The Consul service is created automatically, and - // does not need to be registered - if id == consul.ConsulServiceID && l.config.Server { - continue - } l.serviceStatus[id] = syncStatus{remoteDelete: true} continue } diff --git a/command/agent/local_test.go b/command/agent/local_test.go index 29bf379806..7b1024c91f 100644 --- a/command/agent/local_test.go +++ b/command/agent/local_test.go @@ -119,10 +119,10 @@ func TestAgentAntiEntropy_Services(t *testing.T) { } // Check the local state - if len(agent.state.services) != 3 { + if len(agent.state.services) != 4 { t.Fatalf("bad: %v", agent.state.services) } - if len(agent.state.serviceStatus) != 3 { + if len(agent.state.serviceStatus) != 4 { t.Fatalf("bad: %v", agent.state.serviceStatus) } for name, status := range agent.state.serviceStatus {