| package api |
| |
| import ( |
| "net" |
| "strconv" |
| ) |
| |
| type Weights struct { |
| Passing int |
| Warning int |
| } |
| |
| type Node struct { |
| ID string |
| Node string |
| Address string |
| Datacenter string |
| TaggedAddresses map[string]string |
| Meta map[string]string |
| CreateIndex uint64 |
| ModifyIndex uint64 |
| } |
| |
| type ServiceAddress struct { |
| Address string |
| Port int |
| } |
| |
| type CatalogService struct { |
| ID string |
| Node string |
| Address string |
| Datacenter string |
| TaggedAddresses map[string]string |
| NodeMeta map[string]string |
| ServiceID string |
| ServiceName string |
| ServiceAddress string |
| ServiceTaggedAddresses map[string]ServiceAddress |
| ServiceTags []string |
| ServiceMeta map[string]string |
| ServicePort int |
| ServiceWeights Weights |
| ServiceEnableTagOverride bool |
| ServiceProxy *AgentServiceConnectProxyConfig |
| CreateIndex uint64 |
| Checks HealthChecks |
| ModifyIndex uint64 |
| } |
| |
| type CatalogNode struct { |
| Node *Node |
| Services map[string]*AgentService |
| } |
| |
| type CatalogRegistration struct { |
| ID string |
| Node string |
| Address string |
| TaggedAddresses map[string]string |
| NodeMeta map[string]string |
| Datacenter string |
| Service *AgentService |
| Check *AgentCheck |
| Checks HealthChecks |
| SkipNodeUpdate bool |
| } |
| |
| type CatalogDeregistration struct { |
| Node string |
| Address string // Obsolete. |
| Datacenter string |
| ServiceID string |
| CheckID string |
| } |
| |
| // Catalog can be used to query the Catalog endpoints |
| type Catalog struct { |
| c *Client |
| } |
| |
| // Catalog returns a handle to the catalog endpoints |
| func (c *Client) Catalog() *Catalog { |
| return &Catalog{c} |
| } |
| |
| func (c *Catalog) Register(reg *CatalogRegistration, q *WriteOptions) (*WriteMeta, error) { |
| r := c.c.newRequest("PUT", "/v1/catalog/register") |
| r.setWriteOptions(q) |
| r.obj = reg |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, err |
| } |
| resp.Body.Close() |
| |
| wm := &WriteMeta{} |
| wm.RequestTime = rtt |
| |
| return wm, nil |
| } |
| |
| func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*WriteMeta, error) { |
| r := c.c.newRequest("PUT", "/v1/catalog/deregister") |
| r.setWriteOptions(q) |
| r.obj = dereg |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, err |
| } |
| resp.Body.Close() |
| |
| wm := &WriteMeta{} |
| wm.RequestTime = rtt |
| |
| return wm, nil |
| } |
| |
| // Datacenters is used to query for all the known datacenters |
| func (c *Catalog) Datacenters() ([]string, error) { |
| r := c.c.newRequest("GET", "/v1/catalog/datacenters") |
| _, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, err |
| } |
| defer resp.Body.Close() |
| |
| var out []string |
| if err := decodeBody(resp, &out); err != nil { |
| return nil, err |
| } |
| return out, nil |
| } |
| |
| // Nodes is used to query all the known nodes |
| func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) { |
| r := c.c.newRequest("GET", "/v1/catalog/nodes") |
| r.setQueryOptions(q) |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, nil, err |
| } |
| defer resp.Body.Close() |
| |
| qm := &QueryMeta{} |
| parseQueryMeta(resp, qm) |
| qm.RequestTime = rtt |
| |
| var out []*Node |
| if err := decodeBody(resp, &out); err != nil { |
| return nil, nil, err |
| } |
| return out, qm, nil |
| } |
| |
| // Services is used to query for all known services |
| func (c *Catalog) Services(q *QueryOptions) (map[string][]string, *QueryMeta, error) { |
| r := c.c.newRequest("GET", "/v1/catalog/services") |
| r.setQueryOptions(q) |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, nil, err |
| } |
| defer resp.Body.Close() |
| |
| qm := &QueryMeta{} |
| parseQueryMeta(resp, qm) |
| qm.RequestTime = rtt |
| |
| var out map[string][]string |
| if err := decodeBody(resp, &out); err != nil { |
| return nil, nil, err |
| } |
| return out, qm, nil |
| } |
| |
| // Service is used to query catalog entries for a given service |
| func (c *Catalog) Service(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { |
| var tags []string |
| if tag != "" { |
| tags = []string{tag} |
| } |
| return c.service(service, tags, q, false) |
| } |
| |
| // Supports multiple tags for filtering |
| func (c *Catalog) ServiceMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { |
| return c.service(service, tags, q, false) |
| } |
| |
| // Connect is used to query catalog entries for a given Connect-enabled service |
| func (c *Catalog) Connect(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { |
| var tags []string |
| if tag != "" { |
| tags = []string{tag} |
| } |
| return c.service(service, tags, q, true) |
| } |
| |
| // Supports multiple tags for filtering |
| func (c *Catalog) ConnectMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { |
| return c.service(service, tags, q, true) |
| } |
| |
| func (c *Catalog) service(service string, tags []string, q *QueryOptions, connect bool) ([]*CatalogService, *QueryMeta, error) { |
| path := "/v1/catalog/service/" + service |
| if connect { |
| path = "/v1/catalog/connect/" + service |
| } |
| r := c.c.newRequest("GET", path) |
| r.setQueryOptions(q) |
| if len(tags) > 0 { |
| for _, tag := range tags { |
| r.params.Add("tag", tag) |
| } |
| } |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, nil, err |
| } |
| defer resp.Body.Close() |
| |
| qm := &QueryMeta{} |
| parseQueryMeta(resp, qm) |
| qm.RequestTime = rtt |
| |
| var out []*CatalogService |
| if err := decodeBody(resp, &out); err != nil { |
| return nil, nil, err |
| } |
| return out, qm, nil |
| } |
| |
| // Node is used to query for service information about a single node |
| func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) { |
| r := c.c.newRequest("GET", "/v1/catalog/node/"+node) |
| r.setQueryOptions(q) |
| rtt, resp, err := requireOK(c.c.doRequest(r)) |
| if err != nil { |
| return nil, nil, err |
| } |
| defer resp.Body.Close() |
| |
| qm := &QueryMeta{} |
| parseQueryMeta(resp, qm) |
| qm.RequestTime = rtt |
| |
| var out *CatalogNode |
| if err := decodeBody(resp, &out); err != nil { |
| return nil, nil, err |
| } |
| return out, qm, nil |
| } |
| |
| func ParseServiceAddr(addrPort string) (ServiceAddress, error) { |
| port := 0 |
| host, portStr, err := net.SplitHostPort(addrPort) |
| if err == nil { |
| port, err = strconv.Atoi(portStr) |
| } |
| return ServiceAddress{Address: host, Port: port}, err |
| } |