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  }