clusterviz/consul.go
Ivan Danyliuk a5c6a531fc
Refactor
2018-06-19 17:40:46 +02:00

68 lines
1.6 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
// Consul implements ClusterSource for Consul.
type Consul struct {
hostport string
}
// NewConsul creates new Consul source. It doesn't attempt
// to connect or verify if address is correct.
func NewConsul(hostport string) *Consul {
return &Consul{
hostport: hostport,
}
}
// IPs returns the list of IPs for the given datacenter and tag from Consul.
func (c *Consul) IPs(dc, tag string) ([]string, error) {
url := fmt.Sprintf("http://%s/v1/catalog/service/statusd-rpc?tag=%s", c.hostport, tag)
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("http call failed: %s", err)
}
defer resp.Body.Close()
ips, err := ParseConsulResponse(resp.Body)
if err != nil {
return nil, fmt.Errorf("get nodes list: %s", err)
}
return ips, err
}
// ConsulResponse describes response structure from Consul.
type ConsulResponse []*ConsulNodeInfo
// ConsulNodeInfo describes single node as reported by Consul.
type ConsulNodeInfo struct {
ServiceAddress string
ServicePort int
}
// ToIP converts ConsulNodeInfo fields into hostport representation of IP.
func (c *ConsulNodeInfo) ToIP() string {
return fmt.Sprintf("%s:%d", c.ServiceAddress, c.ServicePort)
}
// ParseConsulResponse parses JSON output from Consul response with
// the list of service and extracts IP addresses.
func ParseConsulResponse(r io.Reader) ([]string, error) {
var resp ConsulResponse
err := json.NewDecoder(r).Decode(&resp)
if err != nil {
return nil, fmt.Errorf("unmarshal Consul JSON response: %s", err)
}
ret := make([]string, len(resp))
for i := range resp {
ret[i] = resp[i].ToIP()
}
return ret, nil
}