github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/fingerprint/consul.go (about) 1 package fingerprint 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "time" 8 9 consul "github.com/hashicorp/consul/api" 10 11 client "github.com/hashicorp/nomad/client/config" 12 "github.com/hashicorp/nomad/nomad/structs" 13 ) 14 15 const ( 16 consulAvailable = "available" 17 consulUnavailable = "unavailable" 18 ) 19 20 // ConsulFingerprint is used to fingerprint for Consul 21 type ConsulFingerprint struct { 22 logger *log.Logger 23 client *consul.Client 24 lastState string 25 } 26 27 // NewConsulFingerprint is used to create a Consul fingerprint 28 func NewConsulFingerprint(logger *log.Logger) Fingerprint { 29 return &ConsulFingerprint{logger: logger, lastState: consulUnavailable} 30 } 31 32 func (f *ConsulFingerprint) Fingerprint(config *client.Config, node *structs.Node) (bool, error) { 33 // Guard against uninitialized Links 34 if node.Links == nil { 35 node.Links = map[string]string{} 36 } 37 38 // Only create the client once to avoid creating too many connections to 39 // Consul. 40 if f.client == nil { 41 consulConfig, err := config.ConsulConfig.ApiConfig() 42 if err != nil { 43 return false, fmt.Errorf("Failed to initialize the Consul client config: %v", err) 44 } 45 46 f.client, err = consul.NewClient(consulConfig) 47 if err != nil { 48 return false, fmt.Errorf("Failed to initialize consul client: %s", err) 49 } 50 } 51 52 // We'll try to detect consul by making a query to to the agent's self API. 53 // If we can't hit this URL consul is probably not running on this machine. 54 info, err := f.client.Agent().Self() 55 if err != nil { 56 // Clear any attributes set by a previous fingerprint. 57 f.clearConsulAttributes(node) 58 59 // Print a message indicating that the Consul Agent is not available 60 // anymore 61 if f.lastState == consulAvailable { 62 f.logger.Printf("[INFO] fingerprint.consul: consul agent is unavailable") 63 } 64 f.lastState = consulUnavailable 65 return false, nil 66 } 67 68 node.Attributes["consul.server"] = strconv.FormatBool(info["Config"]["Server"].(bool)) 69 node.Attributes["consul.version"] = info["Config"]["Version"].(string) 70 node.Attributes["consul.revision"] = info["Config"]["Revision"].(string) 71 node.Attributes["unique.consul.name"] = info["Config"]["NodeName"].(string) 72 node.Attributes["consul.datacenter"] = info["Config"]["Datacenter"].(string) 73 74 node.Links["consul"] = fmt.Sprintf("%s.%s", 75 node.Attributes["consul.datacenter"], 76 node.Attributes["unique.consul.name"]) 77 78 // If the Consul Agent was previously unavailable print a message to 79 // indicate the Agent is available now 80 if f.lastState == consulUnavailable { 81 f.logger.Printf("[INFO] fingerprint.consul: consul agent is available") 82 } 83 f.lastState = consulAvailable 84 return true, nil 85 } 86 87 // clearConsulAttributes removes consul attributes and links from the passed 88 // Node. 89 func (f *ConsulFingerprint) clearConsulAttributes(n *structs.Node) { 90 delete(n.Attributes, "consul.server") 91 delete(n.Attributes, "consul.version") 92 delete(n.Attributes, "consul.revision") 93 delete(n.Attributes, "unique.consul.name") 94 delete(n.Attributes, "consul.datacenter") 95 delete(n.Links, "consul") 96 } 97 98 func (f *ConsulFingerprint) Periodic() (bool, time.Duration) { 99 return true, 15 * time.Second 100 }