Merge pull request #1187 from sfncook/enable_tag_drift_03

Enable tag drift 03
This commit is contained in:
James Phillips 2015-09-11 15:35:32 -07:00
commit 2f9ebdb135
10 changed files with 210 additions and 72 deletions

View File

@ -379,6 +379,9 @@ func (l *localState) setSyncState() error {
}
// If our definition is different, we need to update it
if existing.EnableTagOverride {
existing.Tags = service.Tags
}
equal := reflect.DeepEqual(existing, service)
l.serviceStatus[id] = syncStatus{inSync: equal}
}

View File

@ -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) {
conf := nextConfig()
dir, agent := makeAgent(t, conf)

View File

@ -6,23 +6,25 @@ import (
// ServiceDefinition is used to JSON decode the Service definitions
type ServiceDefinition struct {
ID string
Name string
Tags []string
Address string
Port int
Check CheckType
Checks CheckTypes
Token string
ID string
Name string
Tags []string
Address string
Port int
Check CheckType
Checks CheckTypes
Token string
EnableTagOverride bool
}
func (s *ServiceDefinition) NodeService() *structs.NodeService {
ns := &structs.NodeService{
ID: s.ID,
Service: s.Name,
Tags: s.Tags,
Address: s.Address,
Port: s.Port,
ID: s.ID,
Service: s.Name,
Tags: s.Tags,
Address: s.Address,
Port: s.Port,
EnableTagOverride: s.EnableTagOverride,
}
if ns.ID == "" && ns.Service != "" {
ns.ID = ns.Service

View File

@ -27,7 +27,7 @@ func TestExecCommandRun(t *testing.T) {
code := c.Run(args)
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") {

View File

@ -490,7 +490,7 @@ func TestCatalogListServices(t *testing.T) {
// Just add a node
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 {
t.Fatalf("err: %v", err)
@ -544,7 +544,7 @@ func TestCatalogListServices_Blocking(t *testing.T) {
go func() {
time.Sleep(100 * time.Millisecond)
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
@ -625,7 +625,7 @@ func TestCatalogListServices_Stale(t *testing.T) {
// Inject a fake service
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!
if err := client.Call("Catalog.ListServices", &args, &out); err != nil {
@ -666,7 +666,7 @@ func TestCatalogListServiceNodes(t *testing.T) {
// Just add a node
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 {
t.Fatalf("err: %v", err)
@ -709,8 +709,8 @@ func TestCatalogNodeServices(t *testing.T) {
// Just add a node
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(3, "foo", &structs.NodeService{"web", "web", nil, "127.0.0.1", 80})
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, false})
if err := client.Call("Catalog.NodeServices", &args, &out); err != nil {
t.Fatalf("err: %v", err)

View File

@ -343,10 +343,10 @@ func TestFSM_SnapshotRestore(t *testing.T) {
// Add some state
fsm.state.EnsureNode(1, structs.Node{"foo", "127.0.0.1"})
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(4, "foo", &structs.NodeService{"db", "db", []string{"primary"}, "127.0.0.1", 5000})
fsm.state.EnsureService(5, "baz", &structs.NodeService{"web", "web", nil, "127.0.0.2", 80})
fsm.state.EnsureService(6, "baz", &structs.NodeService{"db", "db", []string{"secondary"}, "127.0.0.2", 5000})
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, false})
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, false})
fsm.state.EnsureCheck(7, &structs.HealthCheck{
Node: "foo",
CheckID: "web",

View File

@ -24,7 +24,7 @@ func TestEnsureRegistration(t *testing.T) {
reg := &structs.RegisterRequest{
Node: "foo",
Address: "127.0.0.1",
Service: &structs.NodeService{"api", "api", nil, "", 5000},
Service: &structs.NodeService{"api", "api", nil, "", 5000, false},
Check: &structs.HealthCheck{
Node: "foo",
CheckID: "api",
@ -189,15 +189,15 @@ func TestEnsureService(t *testing.T) {
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)
}
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)
}
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)
}
@ -234,15 +234,15 @@ func TestEnsureService_DuplicateNode(t *testing.T) {
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)
}
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)
}
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)
}
@ -287,7 +287,7 @@ func TestDeleteNodeService(t *testing.T) {
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)
}
@ -335,11 +335,11 @@ func TestDeleteNodeService_One(t *testing.T) {
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)
}
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)
}
@ -372,7 +372,7 @@ func TestDeleteNode(t *testing.T) {
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)
}
@ -431,15 +431,15 @@ func TestGetServices(t *testing.T) {
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)
}
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)
}
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)
}
@ -481,23 +481,23 @@ func TestServiceNodes(t *testing.T) {
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)
}
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)
}
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)
}
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)
}
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)
}
@ -572,15 +572,15 @@ func TestServiceTagNodes(t *testing.T) {
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)
}
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)
}
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)
}
@ -620,15 +620,15 @@ func TestServiceTagNodes_MultipleTags(t *testing.T) {
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)
}
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)
}
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)
}
@ -696,15 +696,15 @@ func TestStoreSnapshot(t *testing.T) {
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)
}
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)
}
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)
}
@ -889,10 +889,10 @@ func TestStoreSnapshot(t *testing.T) {
}
// 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)
}
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)
}
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 {
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)
}
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 {
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)
}
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 {
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)
}
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 {
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)
}
check := &structs.HealthCheck{
@ -1290,7 +1290,8 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
"statsite-box-stats",
nil,
"",
0}
0,
false}
if err := store.EnsureService(2, "foo", srv); err != nil {
t.Fatalf("err: %v", err)
}
@ -1300,7 +1301,8 @@ func TestSS_Register_Deregister_Query(t *testing.T) {
"statsite-share-stats",
nil,
"",
0}
0,
false}
if err := store.EnsureService(3, "foo", srv); err != nil {
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 {
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)
}
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 {
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)
}
if err := store.EnsureNode(3, structs.Node{"baz", "127.0.0.2"}); err != nil {
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)
}
@ -2577,7 +2579,7 @@ func TestSessionInvalidate_DeleteNodeService(t *testing.T) {
if err := store.EnsureNode(11, structs.Node{"foo", "127.0.0.1"}); err != nil {
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)
}
check := &structs.HealthCheck{

View File

@ -245,11 +245,12 @@ type ServiceNodes []ServiceNode
// NodeService is a service provided by a node
type NodeService struct {
ID string
Service string
Tags []string
Address string
Port int
ID string
Service string
Tags []string
Address string
Port int
EnableTagOverride bool
}
type NodeServices struct {
Node Node

View File

@ -26,6 +26,7 @@ A service definition that is a script looks like:
"tags": ["master"],
"address": "127.0.0.1",
"port": 8000,
"enableTagOverride": false,
"checks": [
{
"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
an `id`, `tags`, `address`, `port`, and `check`. The `id` is set to the `name` if not
provided. It is required that all services have a unique ID per node, so if names
might conflict then unique IDs should be provided.
an `id`, `tags`, `address`, `port`, `check`, and `enableTagOverride`. The `id` is
set to the `name` if not provided. It is required that all services have a unique
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
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).
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
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

View File

@ -135,3 +135,17 @@ fashion.
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
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.