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