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  }