ADd consul support , multiple monitors, config file
This commit is contained in:
115
controller/consul.go
Normal file
115
controller/consul.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/golang/glog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
consulNodeEnv = "CONSUL_NODE"
|
||||
matchTag = "enable_gocast"
|
||||
nodeUrl = "/catalog/node"
|
||||
healthCheckurl = "/health/checks"
|
||||
)
|
||||
|
||||
type ConsulMon struct {
|
||||
addr string
|
||||
node string
|
||||
}
|
||||
|
||||
type ConsulServiceData struct {
|
||||
Services map[string]struct {
|
||||
ID string
|
||||
Service string
|
||||
Tags []string
|
||||
}
|
||||
}
|
||||
|
||||
func contains(inp []string, elem string) bool {
|
||||
for _, a := range inp {
|
||||
if a == elem {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func NewConsulMon(addr string) (*ConsulMon, error) {
|
||||
node := os.Getenv(consulNodeEnv)
|
||||
if node == "" {
|
||||
return nil, fmt.Errorf("%s env variable not set", consulNodeEnv)
|
||||
}
|
||||
return &ConsulMon{addr: addr, node: node}, nil
|
||||
}
|
||||
|
||||
func (c *ConsulMon) queryServices() ([]*App, error) {
|
||||
var apps []*App
|
||||
addr := c.addr + fmt.Sprintf("%s/%s", nodeUrl, c.node)
|
||||
resp, err := http.Get(addr)
|
||||
if err != nil {
|
||||
return apps, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var consulData ConsulServiceData
|
||||
if err := json.NewDecoder(resp.Body).Decode(&consulData); err != nil {
|
||||
return apps, fmt.Errorf("Unable to decode consul data: %v", err)
|
||||
}
|
||||
for _, service := range consulData.Services {
|
||||
if !contains(service.Tags, matchTag) {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
vip string
|
||||
monitors []string
|
||||
)
|
||||
for _, tag := range service.Tags {
|
||||
// try to find the requires tags. Only vip is mandatory
|
||||
parts := strings.Split(tag, "=")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
switch parts[0] {
|
||||
case "vip":
|
||||
vip = parts[1]
|
||||
case "monitor":
|
||||
monitors = append(monitors, parts[1])
|
||||
}
|
||||
}
|
||||
if vip == "" {
|
||||
glog.Errorf("No vip Tag found in matched service :%s", service.Service)
|
||||
continue
|
||||
}
|
||||
app, err := NewApp(service.Service, vip, monitors)
|
||||
if err != nil {
|
||||
glog.Errorf("Unable to add consul app: %v", err)
|
||||
continue
|
||||
}
|
||||
apps = append(apps, app)
|
||||
|
||||
}
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (c *ConsulMon) healthCheck(service string) (bool, error) {
|
||||
addr := c.addr + fmt.Sprintf("%s/%s", healthCheckurl, service)
|
||||
resp, err := http.Get(addr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var data []interface{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, nodeInfo := range data {
|
||||
n := nodeInfo.(map[string]interface{})
|
||||
if n["Node"] == c.node && n["Status"].(string) == "passing" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, fmt.Errorf("No healcheck info found for node %s in consul", c.node)
|
||||
}
|
||||
Reference in New Issue
Block a user