small pixel drawing of a pufferfish cascade

api/catalog.go

package api

import "fmt"

// Node is a Consul-shaped representation of a cluster member.
type Node struct {
	Node    string
	Address string
	Meta    map[string]string
}

// CatalogService describes a single service instance as exposed by the
// /v1/catalog/service/<name> endpoint.
type CatalogService struct {
	Node           string
	Address        string
	ServiceID      string
	ServiceName    string
	ServiceAddress string
	ServicePort    int
	ServiceTags    []string
	ServiceMeta    map[string]string
}

// CatalogNode bundles a node and the services it owns, returned by
// /v1/catalog/node/<name>.
type CatalogNode struct {
	Node     *Node
	Services map[string]*AgentService
}

// Catalog provides access to the cluster-wide read views over gossipped
// service state.
type Catalog struct {
	c *Client
}

// Catalog returns a handle to the catalog endpoints.
func (c *Client) Catalog() *Catalog {
	return &Catalog{c: c}
}

// Services returns the cluster-wide service-name -> tag-union view.
func (cat *Catalog) Services() (map[string][]string, error) {
	r := cat.c.newRequest("GET", "/v1/catalog/services")
	_, resp, err := requireOK(cat.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)
	var out map[string][]string
	if err := decodeJSONBody(resp.Body, &out); err != nil {
		return nil, err
	}
	return out, nil
}

// Service returns every known instance of the named service.
func (cat *Catalog) Service(name string) ([]*CatalogService, error) {
	r := cat.c.newRequest("GET", fmt.Sprintf("/v1/catalog/service/%s", name))
	_, resp, err := requireOK(cat.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)
	var out []*CatalogService
	if err := decodeJSONBody(resp.Body, &out); err != nil {
		return nil, err
	}
	return out, nil
}

// Instances returns every gossipped service instance across the cluster.
// One round trip — useful when you want to render a per-node view rather
// than per-service.
func (cat *Catalog) Instances() ([]*CatalogService, error) {
	r := cat.c.newRequest("GET", "/v1/catalog/instances")
	_, resp, err := requireOK(cat.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)
	var out []*CatalogService
	if err := decodeJSONBody(resp.Body, &out); err != nil {
		return nil, err
	}
	return out, nil
}

// Nodes returns every node serf knows about.
func (cat *Catalog) Nodes() ([]*Node, error) {
	r := cat.c.newRequest("GET", "/v1/catalog/nodes")
	_, resp, err := requireOK(cat.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)
	var out []*Node
	if err := decodeJSONBody(resp.Body, &out); err != nil {
		return nil, err
	}
	return out, nil
}

// Node returns the node and the services it owns.
func (cat *Catalog) Node(name string) (*CatalogNode, error) {
	r := cat.c.newRequest("GET", fmt.Sprintf("/v1/catalog/node/%s", name))
	_, resp, err := requireOK(cat.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)
	var out CatalogNode
	if err := decodeJSONBody(resp.Body, &out); err != nil {
		return nil, err
	}
	return &out, nil
}