2015-08-28 10:26:23 +00:00
|
|
|
package fingerprint
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
consul "github.com/hashicorp/consul/api"
|
|
|
|
|
|
|
|
client "github.com/hashicorp/nomad/client/config"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
)
|
|
|
|
|
2015-12-11 17:01:28 +00:00
|
|
|
const (
|
2015-12-11 21:47:35 +00:00
|
|
|
consulAvailable = "available"
|
|
|
|
consulUnavailable = "unavailable"
|
2015-12-11 17:01:28 +00:00
|
|
|
)
|
|
|
|
|
2016-09-01 20:38:31 +00:00
|
|
|
// ConsulFingerprint is used to fingerprint for Consul
|
2015-08-28 10:26:23 +00:00
|
|
|
type ConsulFingerprint struct {
|
2015-12-11 17:01:28 +00:00
|
|
|
logger *log.Logger
|
|
|
|
client *consul.Client
|
|
|
|
lastState string
|
2015-08-28 10:26:23 +00:00
|
|
|
}
|
|
|
|
|
2016-09-01 18:02:19 +00:00
|
|
|
// NewConsulFingerprint is used to create a Consul fingerprint
|
2015-08-28 10:26:23 +00:00
|
|
|
func NewConsulFingerprint(logger *log.Logger) Fingerprint {
|
2015-12-11 21:47:35 +00:00
|
|
|
return &ConsulFingerprint{logger: logger, lastState: consulUnavailable}
|
2015-08-28 10:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *ConsulFingerprint) Fingerprint(config *client.Config, node *structs.Node) (bool, error) {
|
2015-08-28 10:35:44 +00:00
|
|
|
// Guard against uninitialized Links
|
|
|
|
if node.Links == nil {
|
|
|
|
node.Links = map[string]string{}
|
|
|
|
}
|
|
|
|
|
2015-11-22 21:42:06 +00:00
|
|
|
// Only create the client once to avoid creating too many connections to
|
|
|
|
// Consul.
|
|
|
|
if f.client == nil {
|
2016-05-26 20:31:32 +00:00
|
|
|
consulConfig, err := config.ConsulConfig.ApiConfig()
|
2015-11-22 21:42:06 +00:00
|
|
|
if err != nil {
|
2016-05-26 20:31:32 +00:00
|
|
|
return false, fmt.Errorf("Failed to initialize the Consul client config: %v", err)
|
2015-11-22 21:42:06 +00:00
|
|
|
}
|
2015-08-28 10:26:23 +00:00
|
|
|
|
2015-11-22 21:42:06 +00:00
|
|
|
f.client, err = consul.NewClient(consulConfig)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("Failed to initialize consul client: %s", err)
|
|
|
|
}
|
2015-08-28 10:26:23 +00:00
|
|
|
}
|
|
|
|
|
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.
|
2015-11-22 21:42:06 +00:00
|
|
|
info, err := f.client.Agent().Self()
|
2015-08-28 10:26:23 +00:00
|
|
|
if err != nil {
|
2015-11-22 21:51:10 +00:00
|
|
|
// Clear any attributes set by a previous fingerprint.
|
|
|
|
f.clearConsulAttributes(node)
|
2015-12-11 17:01:28 +00:00
|
|
|
|
|
|
|
// Print a message indicating that the Consul Agent is not available
|
|
|
|
// anymore
|
2015-12-11 21:47:35 +00:00
|
|
|
if f.lastState == consulAvailable {
|
2015-12-11 17:10:21 +00:00
|
|
|
f.logger.Printf("[INFO] fingerprint.consul: consul agent is unavailable")
|
2015-12-11 17:01:28 +00:00
|
|
|
}
|
2015-12-11 21:47:35 +00:00
|
|
|
f.lastState = consulUnavailable
|
2015-11-05 18:39:52 +00:00
|
|
|
return false, nil
|
2015-08-28 10:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
node.Attributes["consul.server"] = strconv.FormatBool(info["Config"]["Server"].(bool))
|
|
|
|
node.Attributes["consul.version"] = info["Config"]["Version"].(string)
|
|
|
|
node.Attributes["consul.revision"] = info["Config"]["Revision"].(string)
|
2016-01-23 02:12:16 +00:00
|
|
|
node.Attributes["unique.consul.name"] = info["Config"]["NodeName"].(string)
|
2015-08-28 10:26:23 +00:00
|
|
|
node.Attributes["consul.datacenter"] = info["Config"]["Datacenter"].(string)
|
|
|
|
|
2015-08-28 10:35:44 +00:00
|
|
|
node.Links["consul"] = fmt.Sprintf("%s.%s",
|
2015-09-01 02:56:25 +00:00
|
|
|
node.Attributes["consul.datacenter"],
|
2016-01-23 02:12:16 +00:00
|
|
|
node.Attributes["unique.consul.name"])
|
2015-08-28 10:35:44 +00:00
|
|
|
|
2015-12-11 17:01:28 +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 17:01:28 +00:00
|
|
|
}
|
2015-12-11 21:47:35 +00:00
|
|
|
f.lastState = consulAvailable
|
2015-08-28 10:26:23 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
2015-11-05 21:46:02 +00:00
|
|
|
|
2015-11-22 21:51:10 +00:00
|
|
|
// clearConsulAttributes removes consul attributes and links from the passed
|
|
|
|
// Node.
|
|
|
|
func (f *ConsulFingerprint) clearConsulAttributes(n *structs.Node) {
|
|
|
|
delete(n.Attributes, "consul.server")
|
|
|
|
delete(n.Attributes, "consul.version")
|
|
|
|
delete(n.Attributes, "consul.revision")
|
2016-01-23 02:12:16 +00:00
|
|
|
delete(n.Attributes, "unique.consul.name")
|
2015-11-22 21:51:10 +00:00
|
|
|
delete(n.Attributes, "consul.datacenter")
|
|
|
|
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
|
|
|
}
|