github.com/anuvu/nomad@v0.8.7-atom1/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 cstructs "github.com/hashicorp/nomad/client/structs" 12 ) 13 14 const ( 15 consulAvailable = "available" 16 consulUnavailable = "unavailable" 17 ) 18 19 // ConsulFingerprint is used to fingerprint for Consul 20 type ConsulFingerprint struct { 21 logger *log.Logger 22 client *consul.Client 23 lastState string 24 } 25 26 // NewConsulFingerprint is used to create a Consul fingerprint 27 func NewConsulFingerprint(logger *log.Logger) Fingerprint { 28 return &ConsulFingerprint{logger: logger, lastState: consulUnavailable} 29 } 30 31 func (f *ConsulFingerprint) Fingerprint(req *cstructs.FingerprintRequest, resp *cstructs.FingerprintResponse) error { 32 // Only create the client once to avoid creating too many connections to 33 // Consul. 34 if f.client == nil { 35 consulConfig, err := req.Config.ConsulConfig.ApiConfig() 36 if err != nil { 37 return fmt.Errorf("Failed to initialize the Consul client config: %v", err) 38 } 39 40 f.client, err = consul.NewClient(consulConfig) 41 if err != nil { 42 return fmt.Errorf("Failed to initialize consul client: %s", err) 43 } 44 } 45 46 // We'll try to detect consul by making a query to to the agent's self API. 47 // If we can't hit this URL consul is probably not running on this machine. 48 info, err := f.client.Agent().Self() 49 if err != nil { 50 f.clearConsulAttributes(resp) 51 52 // Print a message indicating that the Consul Agent is not available 53 // anymore 54 if f.lastState == consulAvailable { 55 f.logger.Printf("[INFO] fingerprint.consul: consul agent is unavailable") 56 } 57 f.lastState = consulUnavailable 58 return nil 59 } 60 61 if s, ok := info["Config"]["Server"].(bool); ok { 62 resp.AddAttribute("consul.server", strconv.FormatBool(s)) 63 } else { 64 f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.server") 65 } 66 if v, ok := info["Config"]["Version"].(string); ok { 67 resp.AddAttribute("consul.version", v) 68 } else { 69 f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.version") 70 } 71 if r, ok := info["Config"]["Revision"].(string); ok { 72 resp.AddAttribute("consul.revision", r) 73 } else { 74 f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.revision") 75 } 76 if n, ok := info["Config"]["NodeName"].(string); ok { 77 resp.AddAttribute("unique.consul.name", n) 78 } else { 79 f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint unique.consul.name") 80 } 81 if d, ok := info["Config"]["Datacenter"].(string); ok { 82 resp.AddAttribute("consul.datacenter", d) 83 } else { 84 f.logger.Printf("[WARN] fingerprint.consul: unable to fingerprint consul.datacenter") 85 } 86 87 if dc, ok := resp.Attributes["consul.datacenter"]; ok { 88 if name, ok2 := resp.Attributes["unique.consul.name"]; ok2 { 89 resp.AddLink("consul", fmt.Sprintf("%s.%s", dc, name)) 90 } 91 } else { 92 f.logger.Printf("[WARN] fingerprint.consul: malformed Consul response prevented linking") 93 } 94 95 // If the Consul Agent was previously unavailable print a message to 96 // indicate the Agent is available now 97 if f.lastState == consulUnavailable { 98 f.logger.Printf("[INFO] fingerprint.consul: consul agent is available") 99 } 100 f.lastState = consulAvailable 101 resp.Detected = true 102 return nil 103 } 104 105 // clearConsulAttributes removes consul attributes and links from the passed 106 // Node. 107 func (f *ConsulFingerprint) clearConsulAttributes(r *cstructs.FingerprintResponse) { 108 r.RemoveAttribute("consul.server") 109 r.RemoveAttribute("consul.version") 110 r.RemoveAttribute("consul.revision") 111 r.RemoveAttribute("unique.consul.name") 112 r.RemoveAttribute("consul.datacenter") 113 r.RemoveLink("consul") 114 } 115 116 func (f *ConsulFingerprint) Periodic() (bool, time.Duration) { 117 return true, 15 * time.Second 118 }