Skip to content

Commit 5057681

Browse files
committed
health: ensure /v1/health/service/:service endpoint returns the most recent results when a filter is used
This is two bugs in two subsystems (blocking queries ; streaming) that make the overall endpoint behave brokenly in the same way to the end user. Simple reproduction (streaming): 1. Register a service with a tag. curl -sL --request PUT 'http://localhost:8500/v1/agent/service/register' \ --header 'Content-Type: application/json' \ --data-raw '{ "ID": "ID1", "Name": "test", "Tags":[ "a" ], "EnableTagOverride": true }' 2. Do an initial filter query that matches on the tag. curl -sLi --get 'http://localhost:8500/v1/health/service/test' --data-urlencode 'filter=a in Service.Tags' 3. Note you get one result. Use the `X-Consul-Index` header to establish a blocking query in another terminal, this should not return yet. curl -sLi --get 'http://localhost:8500/v1/health/service/test?index=$INDEX' --data-urlencode 'filter=a in Service.Tags' 4. Re-register that service with a different tag. curl -sL --request PUT 'http://localhost:8500/v1/agent/service/register' \ --header 'Content-Type: application/json' \ --data-raw '{ "ID": "ID1", "Name": "test", "Tags":[ "b" ], "EnableTagOverride": true }' 5. Your blocking query from (3) should return with a header `X-Consul-Query-Backend: streaming` and empty results if it works correctly `[]`. To reproduce for non-streaming, simply add `&near=_agent` to your read queries and ensure `X-Consul-Query-Backend: blocking-query` shows up in the results.
1 parent e5ed4fe commit 5057681

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

Diff for: agent/consul/health_endpoint.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,15 @@ func (h *Health) ServiceNodes(args *structs.ServiceSpecificRequest, reply *struc
241241
return err
242242
}
243243

244-
reply.Index, reply.Nodes = index, nodes
245244
if len(args.NodeMetaFilters) > 0 {
246-
reply.Nodes = nodeMetaFilter(args.NodeMetaFilters, reply.Nodes)
245+
nodes = nodeMetaFilter(args.NodeMetaFilters, nodes)
247246
}
248247

249-
raw, err := filter.Execute(reply.Nodes)
248+
raw, err := filter.Execute(nodes)
250249
if err != nil {
251250
return err
252251
}
253-
reply.Nodes = raw.(structs.CheckServiceNodes)
252+
nodes = raw.(structs.CheckServiceNodes)
254253

255254
// Note: we filter the results with ACLs *after* applying the user-supplied
256255
// bexpr filter, to ensure QueryMeta.ResultsFilteredByACLs does not include
@@ -259,7 +258,12 @@ func (h *Health) ServiceNodes(args *structs.ServiceSpecificRequest, reply *struc
259258
return err
260259
}
261260

262-
return h.srv.sortNodesByDistanceFrom(args.Source, reply.Nodes)
261+
if err := h.srv.sortNodesByDistanceFrom(args.Source, nodes); err != nil {
262+
return err
263+
}
264+
265+
reply.Index, reply.Nodes = index, nodes
266+
return nil
263267
})
264268

265269
// Provide some metrics

Diff for: agent/rpcclient/health/view.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,12 @@ func (s *healthView) Update(events []*pbsubscribe.Event) error {
8080
return errors.New("check service node was unexpectedly nil")
8181
}
8282
passed, err := s.filter.Evaluate(*csn)
83-
switch {
84-
case err != nil:
83+
if err != nil {
8584
return err
86-
case passed:
85+
} else if passed {
8786
s.state[id] = *csn
87+
} else {
88+
delete(s.state, id)
8889
}
8990

9091
case pbsubscribe.CatalogOp_Deregister:

0 commit comments

Comments
 (0)