open-nomad/client/fingerprint/consul.go

114 lines
3.5 KiB
Go
Raw Normal View History

package fingerprint
import (
"fmt"
"log"
"strconv"
"time"
consul "github.com/hashicorp/consul/api"
cstructs "github.com/hashicorp/nomad/client/structs"
"github.com/hashicorp/nomad/nomad/structs"
)
const (
2015-12-11 21:47:35 +00:00
consulAvailable = "available"
consulUnavailable = "unavailable"
)
2016-09-01 20:38:31 +00:00
// ConsulFingerprint is used to fingerprint for Consul
type ConsulFingerprint struct {
logger *log.Logger
client *consul.Client
lastState string
}
2016-09-01 18:02:19 +00:00
// NewConsulFingerprint is used to create a Consul fingerprint
func NewConsulFingerprint(logger *log.Logger) Fingerprint {
2015-12-11 21:47:35 +00:00
return &ConsulFingerprint{logger: logger, lastState: consulUnavailable}
}
func (f *ConsulFingerprint) Fingerprint(req *cstructs.FingerprintRequest, resp *cstructs.FingerprintResponse) error {
// Only create the client once to avoid creating too many connections to
// Consul.
if f.client == nil {
consulConfig, err := req.Config.ConsulConfig.ApiConfig()
if err != nil {
return fmt.Errorf("Failed to initialize the Consul client config: %v", err)
}
f.client, err = consul.NewClient(consulConfig)
if err != nil {
return fmt.Errorf("Failed to initialize consul client: %s", err)
}
}
2015-09-01 02:56:25 +00:00
// We'll try to detect consul by making a query to to the agent's self API.
// If we can't hit this URL consul is probably not running on this machine.
info, err := f.client.Agent().Self()
if err != nil {
// TODO this should set consul in the response if the error is not nil
// Print a message indicating that the Consul Agent is not available
// anymore
2015-12-11 21:47:35 +00:00
if f.lastState == consulAvailable {
f.logger.Printf("[INFO] fingerprint.consul: consul agent is unavailable")
}
2015-12-11 21:47:35 +00:00
f.lastState = consulUnavailable
return nil
}
if s, ok := info["Config"]["Server"].(bool); ok {
resp.Attributes["consul.server"] = strconv.FormatBool(s)
} else {
f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.server")
}
if v, ok := info["Config"]["Version"].(string); ok {
resp.Attributes["consul.version"] = v
} else {
f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.version")
}
if r, ok := info["Config"]["Revision"].(string); ok {
resp.Attributes["consul.revision"] = r
} else {
f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.revision")
}
if n, ok := info["Config"]["NodeName"].(string); ok {
resp.Attributes["unique.consul.name"] = n
} else {
f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint unique.consul.name")
}
if d, ok := info["Config"]["Datacenter"].(string); ok {
resp.Attributes["consul.datacenter"] = d
} else {
f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.datacenter")
}
if resp.Attributes["consul.datacenter"] != "" || resp.Attributes["unique.consul.name"] != "" {
resp.Links["consul"] = fmt.Sprintf("%s.%s",
resp.Attributes["consul.datacenter"],
resp.Attributes["unique.consul.name"])
} else {
f.logger.Printf("[WARN] fingerprint.consul: malformed Consul response prevented linking")
}
2015-08-28 10:35:44 +00:00
// If the Consul Agent was previously unavailable print a message to
// indicate the Agent is available now
2015-12-11 21:47:35 +00:00
if f.lastState == consulUnavailable {
2015-12-11 21:18:04 +00:00
f.logger.Printf("[INFO] fingerprint.consul: consul agent is available")
}
2015-12-11 21:47:35 +00:00
f.lastState = consulAvailable
return nil
}
2015-11-05 21:46:02 +00:00
// clearConsulAttributes removes consul attributes and links from the passed
// Node.
func (f *ConsulFingerprint) clearConsulAttributes(n *structs.Node) {
delete(n.Links, "consul")
}
2015-11-05 21:46:02 +00:00
func (f *ConsulFingerprint) Periodic() (bool, time.Duration) {
2015-11-05 21:41:41 +00:00
return true, 15 * time.Second
2015-11-05 21:46:02 +00:00
}