mirror of https://github.com/hashicorp/consul
commit
2f9ebdb135
|
@ -379,6 +379,9 @@ func (l *localState) setSyncState() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If our definition is different, we need to update it
|
// If our definition is different, we need to update it
|
||||||
|
if existing.EnableTagOverride {
|
||||||
|
existing.Tags = service.Tags
|
||||||
|
}
|
||||||
equal := reflect.DeepEqual(existing, service)
|
equal := reflect.DeepEqual(existing, service)
|
||||||
l.serviceStatus[id] = syncStatus{inSync: equal}
|
l.serviceStatus[id] = syncStatus{inSync: equal}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,102 @@ func TestAgentAntiEntropy_Services(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAgentAntiEntropy_EnableTagOverride(t *testing.T) {
|
||||||
|
conf := nextConfig()
|
||||||
|
dir, agent := makeAgent(t, conf)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
defer agent.Shutdown()
|
||||||
|
|
||||||
|
testutil.WaitForLeader(t, agent.RPC, "dc1")
|
||||||
|
|
||||||
|
args := &structs.RegisterRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Node: agent.config.NodeName,
|
||||||
|
Address: "127.0.0.1",
|
||||||
|
}
|
||||||
|
var out struct{}
|
||||||
|
|
||||||
|
// EnableTagOverride = true
|
||||||
|
srv1 := &structs.NodeService{
|
||||||
|
ID: "svc_id1",
|
||||||
|
Service: "svc1",
|
||||||
|
Tags: []string{"tag1"},
|
||||||
|
Port: 6100,
|
||||||
|
EnableTagOverride: true,
|
||||||
|
}
|
||||||
|
agent.state.AddService(srv1, "")
|
||||||
|
srv1_mod := new(structs.NodeService)
|
||||||
|
*srv1_mod = *srv1
|
||||||
|
srv1_mod.Port = 7100
|
||||||
|
srv1_mod.Tags = []string{"tag1_mod"}
|
||||||
|
args.Service = srv1_mod
|
||||||
|
if err := agent.RPC("Catalog.Register", args, &out); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableTagOverride = false
|
||||||
|
srv2 := &structs.NodeService{
|
||||||
|
ID: "svc_id2",
|
||||||
|
Service: "svc2",
|
||||||
|
Tags: []string{"tag2"},
|
||||||
|
Port: 6200,
|
||||||
|
EnableTagOverride: false,
|
||||||
|
}
|
||||||
|
agent.state.AddService(srv2, "")
|
||||||
|
srv2_mod := new(structs.NodeService)
|
||||||
|
*srv2_mod = *srv2
|
||||||
|
srv2_mod.Port = 7200
|
||||||
|
srv2_mod.Tags = []string{"tag2_mod"}
|
||||||
|
args.Service = srv2_mod
|
||||||
|
if err := agent.RPC("Catalog.Register", args, &out); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger anti-entropy run and wait
|
||||||
|
agent.StartSync()
|
||||||
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
|
||||||
|
// Verify that we are in sync
|
||||||
|
req := structs.NodeSpecificRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Node: agent.config.NodeName,
|
||||||
|
}
|
||||||
|
var services structs.IndexedNodeServices
|
||||||
|
if err := agent.RPC("Catalog.NodeServices", &req, &services); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the services should match
|
||||||
|
for id, serv := range services.NodeServices.Services {
|
||||||
|
switch id {
|
||||||
|
case "svc_id1":
|
||||||
|
if serv.ID != "svc_id1" ||
|
||||||
|
serv.Service != "svc1" ||
|
||||||
|
serv.Port != 6100 ||
|
||||||
|
!reflect.DeepEqual(serv.Tags, []string{"tag1_mod"}) {
|
||||||
|
t.Fatalf("bad: %v %v", serv, srv1)
|
||||||
|
}
|
||||||
|
case "svc_id2":
|
||||||
|
if serv.ID != "svc_id2" ||
|
||||||
|
serv.Service != "svc2" ||
|
||||||
|
serv.Port != 6200 ||
|
||||||
|
!reflect.DeepEqual(serv.Tags, []string{"tag2"}) {
|
||||||
|
t.Fatalf("bad: %v %v", serv, srv2)
|
||||||
|
}
|
||||||
|
case "consul":
|
||||||
|
// ignore
|
||||||
|
default:
|
||||||
|
t.Fatalf("unexpected service: %v", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, status := range agent.state.serviceStatus {
|
||||||
|
if !status.inSync {
|
||||||
|
t.Fatalf("should be in sync: %v %v", name, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAgentAntiEntropy_Services_WithChecks(t *testing.T) {
|
func TestAgentAntiEntropy_Services_WithChecks(t *testing.T) {
|
||||||
conf := nextConfig()
|
conf := nextConfig()
|
||||||
dir, agent := makeAgent(t, conf)
|
dir, agent := makeAgent(t, conf)
|
||||||
|
|
|
@ -6,23 +6,25 @@ import (
|
||||||
|
|
||||||
// ServiceDefinition is used to JSON decode the Service definitions
|
// ServiceDefinition is used to JSON decode the Service definitions
|
||||||
type ServiceDefinition struct {
|
type ServiceDefinition struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
Tags []string
|
Tags []string
|
||||||
Address string
|
Address string
|
||||||
Port int
|
Port int
|
||||||
Check CheckType
|
Check CheckType
|
||||||
Checks CheckTypes
|
Checks CheckTypes
|
||||||
Token string
|
Token string
|
||||||
|
EnableTagOverride bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServiceDefinition) NodeService() *structs.NodeService {
|
func (s *ServiceDefinition) NodeService() *structs.NodeService {
|
||||||
ns := &structs.NodeService{
|
ns := &structs.NodeService{
|
||||||
ID: s.ID,
|
ID: s.ID,
|
||||||
Service: s.Name,
|
Service: s.Name,
|
||||||
Tags: s.Tags,
|
Tags: s.Tags,
|
||||||
Address: s.Address,
|
Address: s.Address,
|
||||||
Port: s.Port,
|
Port: s.Port,
|
||||||
|
EnableTagOverride: s.EnableTagOverride,
|
||||||
}
|
}
|
||||||
if ns.ID == "" && ns.Service != "" {
|
if ns.ID == "" && ns.Service != "" {
|
||||||
ns.ID = ns.Service
|
ns.ID = ns.Service
|
||||||
|
|
|
@ -27,7 +27,7 @@ func TestExecCommandRun(t *testing.T) {
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d. Error:%#v (std)Output:%#v", code, ui.ErrorWriter.String(), ui.OutputWriter.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(ui.OutputWriter.String(), "load") {
|
if !strings.Contains(ui.OutputWriter.String(), "load") {
|
||||||
|
|
|
@ -490,7 +490,7 @@ func TestCatalogListServices(t *testing.T) {
|
||||||
|
|
||||||
// Just add a node
|
// Just add a node
|
||||||
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
|
|
||||||
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
|
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -544,7 +544,7 @@ func TestCatalogListServices_Blocking(t *testing.T) {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Re-run the query
|
// Re-run the query
|
||||||
|
@ -625,7 +625,7 @@ func TestCatalogListServices_Stale(t *testing.T) {
|
||||||
|
|
||||||
// Inject a fake service
|
// Inject a fake service
|
||||||
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
|
|
||||||
// Run the query, do not wait for leader!
|
// Run the query, do not wait for leader!
|
||||||
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
|
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
|
||||||
|
@ -666,7 +666,7 @@ func TestCatalogListServiceNodes(t *testing.T) {
|
||||||
|
|
||||||
// Just add a node
|
// Just add a node
|
||||||
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
|
|
||||||
if err := client.Call("Catalog.ServiceNodes", &args, &out); err != nil {
|
if err := client.Call("Catalog.ServiceNodes", &args, &out); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -709,8 +709,8 @@ func TestCatalogNodeServices(t *testing.T) {
|
||||||
|
|
||||||
// Just add a node
|
// Just add a node
|
||||||
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
s1.fsm.State().EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80})
|
s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80, false})
|
||||||
|
|
||||||
if err := client.Call("Catalog.NodeServices", &args, &out); err != nil {
|
if err := client.Call("Catalog.NodeServices", &args, &out); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
|
|
@ -343,10 +343,10 @@ func TestFSM_SnapshotRestore(t *testing.T) {
|
||||||
// Add some state
|
// Add some state
|
||||||
fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
|
||||||
fsm.state.EnsureNode(2, structs.Node{"baz", "127.0.0.2"})
|
fsm.state.EnsureNode(2, structs.Node{"baz", "127.0.0.2"})
|
||||||
fsm.state.EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80})
|
fsm.state.EnsureService(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80, false})
|
||||||
fsm.state.EnsureService(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
|
fsm.state.EnsureService(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000, false})
|
||||||
fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, "127.0.0.2", 80})
|
fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, "127.0.0.2", 80, false})
|
||||||
fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, "127.0.0.2", 5000})
|
fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, "127.0.0.2", 5000, false})
|
||||||
fsm.state.EnsureCheck(7, &structs.HealthCheck{
|
fsm.state.EnsureCheck(7, &structs.HealthCheck{
|
||||||
Node: "foo",
|
Node: "foo",
|
||||||
CheckID: "web",
|
CheckID: "web",
|
||||||
|
|
|
@ -24,7 +24,7 @@ func TestEnsureRegistration(t *testing.T) {
|
||||||
reg := &structs.RegisterRequest{
|
reg := &structs.RegisterRequest{
|
||||||
Node: "foo",
|
Node: "foo",
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
Service: &structs.NodeService{"api", "api", nil, "", 5000},
|
Service: &structs.NodeService{"api", "api", nil, "", 5000, false},
|
||||||
Check: &structs.HealthCheck{
|
Check: &structs.HealthCheck{
|
||||||
Node: "foo",
|
Node: "foo",
|
||||||
CheckID: "api",
|
CheckID: "api",
|
||||||
|
@ -189,15 +189,15 @@ func TestEnsureService(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(11, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(11, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5001}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(13, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(13, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,15 +234,15 @@ func TestEnsureService_DuplicateNode(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(11, "foo", &structs.NodeService{"api1", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(11, "foo", &structs.NodeService{"api1", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api2", "api", nil, "", 5001}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api2", "api", nil, "", 5001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(13, "foo", &structs.NodeService{"api3", "api", nil, "", 5002}); err != nil {
|
if err := store.EnsureService(13, "foo", &structs.NodeService{"api3", "api", nil, "", 5002, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ func TestDeleteNodeService(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,11 +335,11 @@ func TestDeleteNodeService_One(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(13, "foo", &structs.NodeService{"api2", "api", nil, "", 5001}); err != nil {
|
if err := store.EnsureService(13, "foo", &structs.NodeService{"api2", "api", nil, "", 5001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ func TestDeleteNode(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(21, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(21, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,15 +431,15 @@ func TestGetServices(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(32, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(32, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(33, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(33, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(34, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
|
if err := store.EnsureService(34, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,23 +481,23 @@ func TestServiceNodes(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(13, "bar", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(13, "bar", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(14, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(14, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(15, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
|
if err := store.EnsureService(15, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(16, "bar", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
|
if err := store.EnsureService(16, "bar", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,15 +572,15 @@ func TestServiceTagNodes(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
|
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
|
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,15 +620,15 @@ func TestServiceTagNodes_MultipleTags(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master", "v2"}, "", 8000}); err != nil {
|
if err := store.EnsureService(17, "foo", &structs.NodeService{"db", "db", []string{"master", "v2"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave", "v2", "dev"}, "", 8001}); err != nil {
|
if err := store.EnsureService(18, "foo", &structs.NodeService{"db2", "db", []string{"slave", "v2", "dev"}, "", 8001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave", "v2"}, "", 8000}); err != nil {
|
if err := store.EnsureService(19, "bar", &structs.NodeService{"db", "db", []string{"slave", "v2"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,15 +696,15 @@ func TestStoreSnapshot(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(10, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(10, "foo", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(11, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001}); err != nil {
|
if err := store.EnsureService(11, "foo", &structs.NodeService{"db2", "db", []string{"slave"}, "", 8001, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.EnsureService(12, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
|
if err := store.EnsureService(12, "bar", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,10 +889,10 @@ func TestStoreSnapshot(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make some changes!
|
// Make some changes!
|
||||||
if err := store.EnsureService(23, "foo", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000}); err != nil {
|
if err := store.EnsureService(23, "foo", &structs.NodeService{"db", "db", []string{"slave"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(24, "bar", &structs.NodeService{"db", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(24, "bar", &structs.NodeService{"db", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureNode(25, structs.Node{"baz", "127.0.0.3"}); err != nil {
|
if err := store.EnsureNode(25, structs.Node{"baz", "127.0.0.3"}); err != nil {
|
||||||
|
@ -1019,7 +1019,7 @@ func TestEnsureCheck(t *testing.T) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
@ -1115,7 +1115,7 @@ func TestDeleteNodeCheck(t *testing.T) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
@ -1165,7 +1165,7 @@ func TestCheckServiceNodes(t *testing.T) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
@ -1246,7 +1246,7 @@ func BenchmarkCheckServiceNodes(t *testing.B) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
@ -1290,7 +1290,8 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
|
||||||
"statsite-box-stats",
|
"statsite-box-stats",
|
||||||
nil,
|
nil,
|
||||||
"",
|
"",
|
||||||
0}
|
0,
|
||||||
|
false}
|
||||||
if err := store.EnsureService(2, "foo", srv); err != nil {
|
if err := store.EnsureService(2, "foo", srv); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1300,7 +1301,8 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
|
||||||
"statsite-share-stats",
|
"statsite-share-stats",
|
||||||
nil,
|
nil,
|
||||||
"",
|
"",
|
||||||
0}
|
0,
|
||||||
|
false}
|
||||||
if err := store.EnsureService(3, "foo", srv); err != nil {
|
if err := store.EnsureService(3, "foo", srv); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1328,7 +1330,7 @@ func TestNodeInfo(t *testing.T) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
@ -1387,13 +1389,13 @@ func TestNodeDump(t *testing.T) {
|
||||||
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(1, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(2, "foo", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureNode(3, structs.Node{"baz", "127.0.0.2"}); err != nil {
|
if err := store.EnsureNode(3, structs.Node{"baz", "127.0.0.2"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(4, "baz", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000}); err != nil {
|
if err := store.EnsureService(4, "baz", &structs.NodeService{"db1", "db", []string{"master"}, "", 8000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2577,7 +2579,7 @@ func TestSessionInvalidate_DeleteNodeService(t *testing.T) {
|
||||||
if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000}); err != nil {
|
if err := store.EnsureService(12, "foo", &structs.NodeService{"api", "api", nil, "", 5000, false}); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
check := &structs.HealthCheck{
|
check := &structs.HealthCheck{
|
||||||
|
|
|
@ -245,11 +245,12 @@ type ServiceNodes []ServiceNode
|
||||||
|
|
||||||
// NodeService is a service provided by a node
|
// NodeService is a service provided by a node
|
||||||
type NodeService struct {
|
type NodeService struct {
|
||||||
ID string
|
ID string
|
||||||
Service string
|
Service string
|
||||||
Tags []string
|
Tags []string
|
||||||
Address string
|
Address string
|
||||||
Port int
|
Port int
|
||||||
|
EnableTagOverride bool
|
||||||
}
|
}
|
||||||
type NodeServices struct {
|
type NodeServices struct {
|
||||||
Node Node
|
Node Node
|
||||||
|
|
|
@ -26,6 +26,7 @@ A service definition that is a script looks like:
|
||||||
"tags": ["master"],
|
"tags": ["master"],
|
||||||
"address": "127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port": 8000,
|
"port": 8000,
|
||||||
|
"enableTagOverride": false,
|
||||||
"checks": [
|
"checks": [
|
||||||
{
|
{
|
||||||
"script": "/usr/local/bin/check_redis.py",
|
"script": "/usr/local/bin/check_redis.py",
|
||||||
|
@ -37,9 +38,9 @@ A service definition that is a script looks like:
|
||||||
```
|
```
|
||||||
|
|
||||||
A service definition must include a `name` and may optionally provide
|
A service definition must include a `name` and may optionally provide
|
||||||
an `id`, `tags`, `address`, `port`, and `check`. The `id` is set to the `name` if not
|
an `id`, `tags`, `address`, `port`, `check`, and `enableTagOverride`. The `id` is
|
||||||
provided. It is required that all services have a unique ID per node, so if names
|
set to the `name` if not provided. It is required that all services have a unique
|
||||||
might conflict then unique IDs should be provided.
|
ID per node, so if names might conflict then unique IDs should be provided.
|
||||||
|
|
||||||
The `tags` property is a list of values that are opaque to Consul but can be used to
|
The `tags` property is a list of values that are opaque to Consul but can be used to
|
||||||
distinguish between "master" or "slave" nodes, different versions, or any other service
|
distinguish between "master" or "slave" nodes, different versions, or any other service
|
||||||
|
@ -73,6 +74,25 @@ from `1`.
|
||||||
|
|
||||||
Note: there is more information about [checks here](/docs/agent/checks.html).
|
Note: there is more information about [checks here](/docs/agent/checks.html).
|
||||||
|
|
||||||
|
The `enableTagOverride` can optionally be specified to disable the anti-entropy
|
||||||
|
feature for this service. If enableTagOverride is set to TRUE then external
|
||||||
|
agents can update this service in the [catalog](/docs/agent/http/catalog.html) and modify the tags. Subsequent
|
||||||
|
local sync operations by this agent will ignore the updated tags. For instance: If an external agent
|
||||||
|
modified both the tags and the port for this service and `enableTagOverride`
|
||||||
|
was set to TRUE then after the next sync cycle the service's port would revert
|
||||||
|
to the original value but the tags would maintain the updated value. As a
|
||||||
|
counter example: If an external agent modified both the tags and port for this
|
||||||
|
service and `enableTagOverride` was set to FALSE then after the next sync
|
||||||
|
cycle the service's port AND the tags would revert to the original value and
|
||||||
|
all modifications would be lost. It's important to note that this applies only
|
||||||
|
to the locally registered service. If you have multiple nodes all registering
|
||||||
|
the same service their `enableTagOverride` configuration and all other service
|
||||||
|
configuration items are independant of one another. Updating the tags for
|
||||||
|
the service registered on one node is independant of the same service (by name)
|
||||||
|
registered on another node. If `enableTagOverride` is not specified the default
|
||||||
|
value is false. See [anti-entropy syncs](/docs/internals/anti-entropy.html)
|
||||||
|
for more info.
|
||||||
|
|
||||||
To configure a service, either provide it as a `-config-file` option to the
|
To configure a service, either provide it as a `-config-file` option to the
|
||||||
agent or place it inside the `-config-dir` of the agent. The file must
|
agent or place it inside the `-config-dir` of the agent. The file must
|
||||||
end in the ".json" extension to be loaded by Consul. Check definitions can
|
end in the ".json" extension to be loaded by Consul. Check definitions can
|
||||||
|
|
|
@ -135,3 +135,17 @@ fashion.
|
||||||
If an error is encountered during an anti-entropy run, the error is logged and
|
If an error is encountered during an anti-entropy run, the error is logged and
|
||||||
the agent continues to run. The anti-entropy mechanism is run periodically to
|
the agent continues to run. The anti-entropy mechanism is run periodically to
|
||||||
automatically recover from these types of transient failures.
|
automatically recover from these types of transient failures.
|
||||||
|
|
||||||
|
### EnableTagOverride
|
||||||
|
|
||||||
|
Synchronization of service registration can be partially modified to allow
|
||||||
|
external agents to change the tags for a service. This can be useful in
|
||||||
|
situations where an external monitoring service needs to be the source of
|
||||||
|
truth for tag information. For instance: Redis DB and its monitoring service
|
||||||
|
Redis Sentinel have this kind of relationship. Redis instances are responsible
|
||||||
|
for much of their configuration, but Sentinels determine whether the Redis
|
||||||
|
instance is a master or a slave. Using the Consul service configuration item
|
||||||
|
[EnableTagOverride](/docs/agent/services.html) you can instruct the Consul
|
||||||
|
agent on which the Redis DB is running to NOT update the tags during anti-entropy
|
||||||
|
synchronization. For more information see [Services](/docs/agent/services.html)
|
||||||
|
page.
|
||||||
|
|
Loading…
Reference in New Issue