Skip to content

Commit 57a45ea

Browse files
committed
Merge pull request #68 from hashicorp/f-consistency
Adding support for "stale" and "consistent" read modes
2 parents c1bd716 + 23dd1a0 commit 57a45ea

16 files changed

+745
-198
lines changed

command/agent/catalog_endpoint.go

+26-22
Original file line numberDiff line numberDiff line change
@@ -57,39 +57,41 @@ func (s *HTTPServer) CatalogDatacenters(resp http.ResponseWriter, req *http.Requ
5757
return out, nil
5858
}
5959

60-
func (s *HTTPServer) CatalogNodes(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
60+
func (s *HTTPServer) CatalogNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
6161
// Setup the request
6262
args := structs.DCSpecificRequest{}
63-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
64-
return 0, nil, nil
63+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
64+
return nil, nil
6565
}
6666

6767
var out structs.IndexedNodes
68+
defer setMeta(resp, &out.QueryMeta)
6869
if err := s.agent.RPC("Catalog.ListNodes", &args, &out); err != nil {
69-
return 0, nil, err
70+
return nil, err
7071
}
71-
return out.Index, out.Nodes, nil
72+
return out.Nodes, nil
7273
}
7374

74-
func (s *HTTPServer) CatalogServices(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
75+
func (s *HTTPServer) CatalogServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
7576
// Set default DC
7677
args := structs.DCSpecificRequest{}
77-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
78-
return 0, nil, nil
78+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
79+
return nil, nil
7980
}
8081

8182
var out structs.IndexedServices
83+
defer setMeta(resp, &out.QueryMeta)
8284
if err := s.agent.RPC("Catalog.ListServices", &args, &out); err != nil {
83-
return 0, nil, err
85+
return nil, err
8486
}
85-
return out.Index, out.Services, nil
87+
return out.Services, nil
8688
}
8789

88-
func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
90+
func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
8991
// Set default DC
9092
args := structs.ServiceSpecificRequest{}
91-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
92-
return 0, nil, nil
93+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
94+
return nil, nil
9395
}
9496

9597
// Check for a tag
@@ -104,36 +106,38 @@ func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Req
104106
if args.ServiceName == "" {
105107
resp.WriteHeader(400)
106108
resp.Write([]byte("Missing service name"))
107-
return 0, nil, nil
109+
return nil, nil
108110
}
109111

110112
// Make the RPC request
111113
var out structs.IndexedServiceNodes
114+
defer setMeta(resp, &out.QueryMeta)
112115
if err := s.agent.RPC("Catalog.ServiceNodes", &args, &out); err != nil {
113-
return 0, nil, err
116+
return nil, err
114117
}
115-
return out.Index, out.ServiceNodes, nil
118+
return out.ServiceNodes, nil
116119
}
117120

118-
func (s *HTTPServer) CatalogNodeServices(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
121+
func (s *HTTPServer) CatalogNodeServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
119122
// Set default Datacenter
120123
args := structs.NodeSpecificRequest{}
121-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
122-
return 0, nil, nil
124+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
125+
return nil, nil
123126
}
124127

125128
// Pull out the node name
126129
args.Node = strings.TrimPrefix(req.URL.Path, "/v1/catalog/node/")
127130
if args.Node == "" {
128131
resp.WriteHeader(400)
129132
resp.Write([]byte("Missing node name"))
130-
return 0, nil, nil
133+
return nil, nil
131134
}
132135

133136
// Make the RPC request
134137
var out structs.IndexedNodeServices
138+
defer setMeta(resp, &out.QueryMeta)
135139
if err := s.agent.RPC("Catalog.NodeServices", &args, &out); err != nil {
136-
return 0, nil, err
140+
return nil, err
137141
}
138-
return out.Index, out.NodeServices, nil
142+
return out.NodeServices, nil
139143
}

command/agent/catalog_endpoint_test.go

+17-19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"github.com/hashicorp/consul/consul/structs"
66
"net/http"
7+
"net/http/httptest"
78
"os"
89
"testing"
910
"time"
@@ -115,14 +116,14 @@ func TestCatalogNodes(t *testing.T) {
115116
t.Fatalf("err: %v", err)
116117
}
117118

118-
idx, obj, err := srv.CatalogNodes(nil, req)
119+
resp := httptest.NewRecorder()
120+
obj, err := srv.CatalogNodes(resp, req)
119121
if err != nil {
120122
t.Fatalf("err: %v", err)
121123
}
122124

123-
if idx == 0 {
124-
t.Fatalf("bad: %v", idx)
125-
}
125+
// Verify an index is set
126+
assertIndex(t, resp)
126127

127128
nodes := obj.(structs.Nodes)
128129
if len(nodes) != 2 {
@@ -170,7 +171,8 @@ func TestCatalogNodes_Blocking(t *testing.T) {
170171
t.Fatalf("err: %v", err)
171172
}
172173

173-
idx, obj, err := srv.CatalogNodes(nil, req)
174+
resp := httptest.NewRecorder()
175+
obj, err := srv.CatalogNodes(resp, req)
174176
if err != nil {
175177
t.Fatalf("err: %v", err)
176178
}
@@ -180,7 +182,7 @@ func TestCatalogNodes_Blocking(t *testing.T) {
180182
t.Fatalf("too fast")
181183
}
182184

183-
if idx <= out.Index {
185+
if idx := getIndex(t, resp); idx <= out.Index {
184186
t.Fatalf("bad: %v", idx)
185187
}
186188

@@ -218,14 +220,13 @@ func TestCatalogServices(t *testing.T) {
218220
t.Fatalf("err: %v", err)
219221
}
220222

221-
idx, obj, err := srv.CatalogServices(nil, req)
223+
resp := httptest.NewRecorder()
224+
obj, err := srv.CatalogServices(resp, req)
222225
if err != nil {
223226
t.Fatalf("err: %v", err)
224227
}
225228

226-
if idx == 0 {
227-
t.Fatalf("bad: %v", idx)
228-
}
229+
assertIndex(t, resp)
229230

230231
services := obj.(structs.Services)
231232
if len(services) != 2 {
@@ -262,14 +263,13 @@ func TestCatalogServiceNodes(t *testing.T) {
262263
t.Fatalf("err: %v", err)
263264
}
264265

265-
idx, obj, err := srv.CatalogServiceNodes(nil, req)
266+
resp := httptest.NewRecorder()
267+
obj, err := srv.CatalogServiceNodes(resp, req)
266268
if err != nil {
267269
t.Fatalf("err: %v", err)
268270
}
269271

270-
if idx == 0 {
271-
t.Fatalf("bad: %v", idx)
272-
}
272+
assertIndex(t, resp)
273273

274274
nodes := obj.(structs.ServiceNodes)
275275
if len(nodes) != 1 {
@@ -306,14 +306,12 @@ func TestCatalogNodeServices(t *testing.T) {
306306
t.Fatalf("err: %v", err)
307307
}
308308

309-
idx, obj, err := srv.CatalogNodeServices(nil, req)
309+
resp := httptest.NewRecorder()
310+
obj, err := srv.CatalogNodeServices(resp, req)
310311
if err != nil {
311312
t.Fatalf("err: %v", err)
312313
}
313-
314-
if idx == 0 {
315-
t.Fatalf("bad: %v", idx)
316-
}
314+
assertIndex(t, resp)
317315

318316
services := obj.(*structs.NodeServices)
319317
if len(services.Services) != 1 {

command/agent/health_endpoint.go

+28-24
Original file line numberDiff line numberDiff line change
@@ -6,80 +6,83 @@ import (
66
"strings"
77
)
88

9-
func (s *HTTPServer) HealthChecksInState(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
9+
func (s *HTTPServer) HealthChecksInState(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
1010
// Set default DC
1111
args := structs.ChecksInStateRequest{}
12-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
13-
return 0, nil, nil
12+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
13+
return nil, nil
1414
}
1515

1616
// Pull out the service name
1717
args.State = strings.TrimPrefix(req.URL.Path, "/v1/health/state/")
1818
if args.State == "" {
1919
resp.WriteHeader(400)
2020
resp.Write([]byte("Missing check state"))
21-
return 0, nil, nil
21+
return nil, nil
2222
}
2323

2424
// Make the RPC request
2525
var out structs.IndexedHealthChecks
26+
defer setMeta(resp, &out.QueryMeta)
2627
if err := s.agent.RPC("Health.ChecksInState", &args, &out); err != nil {
27-
return 0, nil, err
28+
return nil, err
2829
}
29-
return out.Index, out.HealthChecks, nil
30+
return out.HealthChecks, nil
3031
}
3132

32-
func (s *HTTPServer) HealthNodeChecks(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
33+
func (s *HTTPServer) HealthNodeChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
3334
// Set default DC
3435
args := structs.NodeSpecificRequest{}
35-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
36-
return 0, nil, nil
36+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
37+
return nil, nil
3738
}
3839

3940
// Pull out the service name
4041
args.Node = strings.TrimPrefix(req.URL.Path, "/v1/health/node/")
4142
if args.Node == "" {
4243
resp.WriteHeader(400)
4344
resp.Write([]byte("Missing node name"))
44-
return 0, nil, nil
45+
return nil, nil
4546
}
4647

4748
// Make the RPC request
4849
var out structs.IndexedHealthChecks
50+
defer setMeta(resp, &out.QueryMeta)
4951
if err := s.agent.RPC("Health.NodeChecks", &args, &out); err != nil {
50-
return 0, nil, err
52+
return nil, err
5153
}
52-
return out.Index, out.HealthChecks, nil
54+
return out.HealthChecks, nil
5355
}
5456

55-
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
57+
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
5658
// Set default DC
5759
args := structs.ServiceSpecificRequest{}
58-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
59-
return 0, nil, nil
60+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
61+
return nil, nil
6062
}
6163

6264
// Pull out the service name
6365
args.ServiceName = strings.TrimPrefix(req.URL.Path, "/v1/health/checks/")
6466
if args.ServiceName == "" {
6567
resp.WriteHeader(400)
6668
resp.Write([]byte("Missing service name"))
67-
return 0, nil, nil
69+
return nil, nil
6870
}
6971

7072
// Make the RPC request
7173
var out structs.IndexedHealthChecks
74+
defer setMeta(resp, &out.QueryMeta)
7275
if err := s.agent.RPC("Health.ServiceChecks", &args, &out); err != nil {
73-
return 0, nil, err
76+
return nil, err
7477
}
75-
return out.Index, out.HealthChecks, nil
78+
return out.HealthChecks, nil
7679
}
7780

78-
func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Request) (uint64, interface{}, error) {
81+
func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
7982
// Set default DC
8083
args := structs.ServiceSpecificRequest{}
81-
if done := s.parse(resp, req, &args.Datacenter, &args.BlockingQuery); done {
82-
return 0, nil, nil
84+
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
85+
return nil, nil
8386
}
8487

8588
// Check for a tag
@@ -94,13 +97,14 @@ func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Requ
9497
if args.ServiceName == "" {
9598
resp.WriteHeader(400)
9699
resp.Write([]byte("Missing service name"))
97-
return 0, nil, nil
100+
return nil, nil
98101
}
99102

100103
// Make the RPC request
101104
var out structs.IndexedCheckServiceNodes
105+
defer setMeta(resp, &out.QueryMeta)
102106
if err := s.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
103-
return 0, nil, err
107+
return nil, err
104108
}
105-
return out.Index, out.Nodes, nil
109+
return out.Nodes, nil
106110
}

0 commit comments

Comments
 (0)