github.com/ranjib/nomad@v0.1.1-0.20160225204057-97751b02f70b/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 the architecture 21 type ConsulFingerprint struct { 22 logger *log.Logger 23 client *consul.Client 24 lastState string 25 } 26 27 // NewConsulFingerprint is used to create an OS 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 address := config.ReadDefault("consul.address", "127.0.0.1:8500") 42 timeout, err := time.ParseDuration(config.ReadDefault("consul.timeout", "10ms")) 43 if err != nil { 44 return false, fmt.Errorf("Unable to parse consul.timeout: %s", err) 45 } 46 47 consulConfig := consul.DefaultConfig() 48 consulConfig.Address = address 49 consulConfig.HttpClient.Timeout = timeout 50 51 f.client, err = consul.NewClient(consulConfig) 52 if err != nil { 53 return false, fmt.Errorf("Failed to initialize consul client: %s", err) 54 } 55 } 56 57 // We'll try to detect consul by making a query to to the agent's self API. 58 // If we can't hit this URL consul is probably not running on this machine. 59 info, err := f.client.Agent().Self() 60 if err != nil { 61 // Clear any attributes set by a previous fingerprint. 62 f.clearConsulAttributes(node) 63 64 // Print a message indicating that the Consul Agent is not available 65 // anymore 66 if f.lastState == consulAvailable { 67 f.logger.Printf("[INFO] fingerprint.consul: consul agent is unavailable") 68 } 69 f.lastState = consulUnavailable 70 return false, nil 71 } 72 73 node.Attributes["consul.server"] = strconv.FormatBool(info["Config"]["Server"].(bool)) 74 node.Attributes["consul.version"] = info["Config"]["Version"].(string) 75 node.Attributes["consul.revision"] = info["Config"]["Revision"].(string) 76 node.Attributes["unique.consul.name"] = info["Config"]["NodeName"].(string) 77 node.Attributes["consul.datacenter"] = info["Config"]["Datacenter"].(string) 78 79 node.Links["consul"] = fmt.Sprintf("%s.%s", 80 node.Attributes["consul.datacenter"], 81 node.Attributes["unique.consul.name"]) 82 83 // If the Consul Agent was previously unavailable print a message to 84 // indicate the Agent is available now 85 if f.lastState == consulUnavailable { 86 f.logger.Printf("[INFO] fingerprint.consul: consul agent is available") 87 } 88 f.lastState = consulAvailable 89 return true, nil 90 } 91 92 // clearConsulAttributes removes consul attributes and links from the passed 93 // Node. 94 func (f *ConsulFingerprint) clearConsulAttributes(n *structs.Node) { 95 delete(n.Attributes, "consul.server") 96 delete(n.Attributes, "consul.version") 97 delete(n.Attributes, "consul.revision") 98 delete(n.Attributes, "unique.consul.name") 99 delete(n.Attributes, "consul.datacenter") 100 delete(n.Links, "consul") 101 } 102 103 func (f *ConsulFingerprint) Periodic() (bool, time.Duration) { 104 return true, 15 * time.Second 105 }