github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/fingerprint/vault.go (about)

     1  package fingerprint
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	client "github.com/hashicorp/nomad/client/config"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  	vapi "github.com/hashicorp/vault/api"
    13  )
    14  
    15  const (
    16  	vaultAvailable   = "available"
    17  	vaultUnavailable = "unavailable"
    18  )
    19  
    20  // VaultFingerprint is used to fingerprint for Vault
    21  type VaultFingerprint struct {
    22  	logger    *log.Logger
    23  	client    *vapi.Client
    24  	lastState string
    25  }
    26  
    27  // NewVaultFingerprint is used to create a Vault fingerprint
    28  func NewVaultFingerprint(logger *log.Logger) Fingerprint {
    29  	return &VaultFingerprint{logger: logger, lastState: vaultUnavailable}
    30  }
    31  
    32  func (f *VaultFingerprint) Fingerprint(config *client.Config, node *structs.Node) (bool, error) {
    33  	if config.VaultConfig == nil || !config.VaultConfig.IsEnabled() {
    34  		return false, nil
    35  	}
    36  
    37  	// Only create the client once to avoid creating too many connections to
    38  	// Vault.
    39  	if f.client == nil {
    40  		vaultConfig, err := config.VaultConfig.ApiConfig()
    41  		if err != nil {
    42  			return false, fmt.Errorf("Failed to initialize the Vault client config: %v", err)
    43  		}
    44  
    45  		f.client, err = vapi.NewClient(vaultConfig)
    46  		if err != nil {
    47  			return false, fmt.Errorf("Failed to initialize Vault client: %s", err)
    48  		}
    49  	}
    50  
    51  	// Connect to vault and parse its information
    52  	status, err := f.client.Sys().SealStatus()
    53  	if err != nil {
    54  		// Clear any attributes set by a previous fingerprint.
    55  		f.clearVaultAttributes(node)
    56  
    57  		// Print a message indicating that Vault is not available anymore
    58  		if f.lastState == vaultAvailable {
    59  			f.logger.Printf("[INFO] fingerprint.vault: Vault is unavailable")
    60  		}
    61  		f.lastState = vaultUnavailable
    62  		return false, nil
    63  	}
    64  
    65  	node.Attributes["vault.accessible"] = strconv.FormatBool(true)
    66  	// We strip the Vault prefix becasue < 0.6.2 the version looks like:
    67  	// status.Version = "Vault v0.6.1"
    68  	node.Attributes["vault.version"] = strings.TrimPrefix(status.Version, "Vault ")
    69  	node.Attributes["vault.cluster_id"] = status.ClusterID
    70  	node.Attributes["vault.cluster_name"] = status.ClusterName
    71  
    72  	// If Vault was previously unavailable print a message to indicate the Agent
    73  	// is available now
    74  	if f.lastState == vaultUnavailable {
    75  		f.logger.Printf("[INFO] fingerprint.vault: Vault is available")
    76  	}
    77  	f.lastState = vaultAvailable
    78  	return true, nil
    79  }
    80  
    81  func (f *VaultFingerprint) clearVaultAttributes(n *structs.Node) {
    82  	delete(n.Attributes, "vault.accessible")
    83  	delete(n.Attributes, "vault.version")
    84  	delete(n.Attributes, "vault.cluster_id")
    85  	delete(n.Attributes, "vault.cluster_name")
    86  }
    87  
    88  func (f *VaultFingerprint) Periodic() (bool, time.Duration) {
    89  	return true, 15 * time.Second
    90  }