blob: c175c3fff53b3ce997b419930a4e6e2504910c3c [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001package api
2
3type Weights struct {
4 Passing int
5 Warning int
6}
7
8type Node struct {
9 ID string
10 Node string
11 Address string
12 Datacenter string
13 TaggedAddresses map[string]string
14 Meta map[string]string
15 CreateIndex uint64
16 ModifyIndex uint64
17}
18
19type CatalogService struct {
20 ID string
21 Node string
22 Address string
23 Datacenter string
24 TaggedAddresses map[string]string
25 NodeMeta map[string]string
26 ServiceID string
27 ServiceName string
28 ServiceAddress string
29 ServiceTags []string
30 ServiceMeta map[string]string
31 ServicePort int
32 ServiceWeights Weights
33 ServiceEnableTagOverride bool
34 // DEPRECATED (ProxyDestination) - remove the next comment!
35 // We forgot to ever add ServiceProxyDestination here so no need to deprecate!
36 ServiceProxy *AgentServiceConnectProxyConfig
37 CreateIndex uint64
38 Checks HealthChecks
39 ModifyIndex uint64
40}
41
42type CatalogNode struct {
43 Node *Node
44 Services map[string]*AgentService
45}
46
47type CatalogRegistration struct {
48 ID string
49 Node string
50 Address string
51 TaggedAddresses map[string]string
52 NodeMeta map[string]string
53 Datacenter string
54 Service *AgentService
55 Check *AgentCheck
56 Checks HealthChecks
57 SkipNodeUpdate bool
58}
59
60type CatalogDeregistration struct {
61 Node string
62 Address string // Obsolete.
63 Datacenter string
64 ServiceID string
65 CheckID string
66}
67
68// Catalog can be used to query the Catalog endpoints
69type Catalog struct {
70 c *Client
71}
72
73// Catalog returns a handle to the catalog endpoints
74func (c *Client) Catalog() *Catalog {
75 return &Catalog{c}
76}
77
78func (c *Catalog) Register(reg *CatalogRegistration, q *WriteOptions) (*WriteMeta, error) {
79 r := c.c.newRequest("PUT", "/v1/catalog/register")
80 r.setWriteOptions(q)
81 r.obj = reg
82 rtt, resp, err := requireOK(c.c.doRequest(r))
83 if err != nil {
84 return nil, err
85 }
86 resp.Body.Close()
87
88 wm := &WriteMeta{}
89 wm.RequestTime = rtt
90
91 return wm, nil
92}
93
94func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*WriteMeta, error) {
95 r := c.c.newRequest("PUT", "/v1/catalog/deregister")
96 r.setWriteOptions(q)
97 r.obj = dereg
98 rtt, resp, err := requireOK(c.c.doRequest(r))
99 if err != nil {
100 return nil, err
101 }
102 resp.Body.Close()
103
104 wm := &WriteMeta{}
105 wm.RequestTime = rtt
106
107 return wm, nil
108}
109
110// Datacenters is used to query for all the known datacenters
111func (c *Catalog) Datacenters() ([]string, error) {
112 r := c.c.newRequest("GET", "/v1/catalog/datacenters")
113 _, resp, err := requireOK(c.c.doRequest(r))
114 if err != nil {
115 return nil, err
116 }
117 defer resp.Body.Close()
118
119 var out []string
120 if err := decodeBody(resp, &out); err != nil {
121 return nil, err
122 }
123 return out, nil
124}
125
126// Nodes is used to query all the known nodes
127func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) {
128 r := c.c.newRequest("GET", "/v1/catalog/nodes")
129 r.setQueryOptions(q)
130 rtt, resp, err := requireOK(c.c.doRequest(r))
131 if err != nil {
132 return nil, nil, err
133 }
134 defer resp.Body.Close()
135
136 qm := &QueryMeta{}
137 parseQueryMeta(resp, qm)
138 qm.RequestTime = rtt
139
140 var out []*Node
141 if err := decodeBody(resp, &out); err != nil {
142 return nil, nil, err
143 }
144 return out, qm, nil
145}
146
147// Services is used to query for all known services
148func (c *Catalog) Services(q *QueryOptions) (map[string][]string, *QueryMeta, error) {
149 r := c.c.newRequest("GET", "/v1/catalog/services")
150 r.setQueryOptions(q)
151 rtt, resp, err := requireOK(c.c.doRequest(r))
152 if err != nil {
153 return nil, nil, err
154 }
155 defer resp.Body.Close()
156
157 qm := &QueryMeta{}
158 parseQueryMeta(resp, qm)
159 qm.RequestTime = rtt
160
161 var out map[string][]string
162 if err := decodeBody(resp, &out); err != nil {
163 return nil, nil, err
164 }
165 return out, qm, nil
166}
167
168// Service is used to query catalog entries for a given service
169func (c *Catalog) Service(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) {
170 var tags []string
171 if tag != "" {
172 tags = []string{tag}
173 }
174 return c.service(service, tags, q, false)
175}
176
177// Supports multiple tags for filtering
178func (c *Catalog) ServiceMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) {
179 return c.service(service, tags, q, false)
180}
181
182// Connect is used to query catalog entries for a given Connect-enabled service
183func (c *Catalog) Connect(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) {
184 var tags []string
185 if tag != "" {
186 tags = []string{tag}
187 }
188 return c.service(service, tags, q, true)
189}
190
191// Supports multiple tags for filtering
192func (c *Catalog) ConnectMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) {
193 return c.service(service, tags, q, true)
194}
195
196func (c *Catalog) service(service string, tags []string, q *QueryOptions, connect bool) ([]*CatalogService, *QueryMeta, error) {
197 path := "/v1/catalog/service/" + service
198 if connect {
199 path = "/v1/catalog/connect/" + service
200 }
201 r := c.c.newRequest("GET", path)
202 r.setQueryOptions(q)
203 if len(tags) > 0 {
204 for _, tag := range tags {
205 r.params.Add("tag", tag)
206 }
207 }
208 rtt, resp, err := requireOK(c.c.doRequest(r))
209 if err != nil {
210 return nil, nil, err
211 }
212 defer resp.Body.Close()
213
214 qm := &QueryMeta{}
215 parseQueryMeta(resp, qm)
216 qm.RequestTime = rtt
217
218 var out []*CatalogService
219 if err := decodeBody(resp, &out); err != nil {
220 return nil, nil, err
221 }
222 return out, qm, nil
223}
224
225// Node is used to query for service information about a single node
226func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) {
227 r := c.c.newRequest("GET", "/v1/catalog/node/"+node)
228 r.setQueryOptions(q)
229 rtt, resp, err := requireOK(c.c.doRequest(r))
230 if err != nil {
231 return nil, nil, err
232 }
233 defer resp.Body.Close()
234
235 qm := &QueryMeta{}
236 parseQueryMeta(resp, qm)
237 qm.RequestTime = rtt
238
239 var out *CatalogNode
240 if err := decodeBody(resp, &out); err != nil {
241 return nil, nil, err
242 }
243 return out, qm, nil
244}