1package fingerprint 2 3import ( 4 "fmt" 5 "sort" 6 "time" 7 8 log "github.com/hashicorp/go-hclog" 9 cstructs "github.com/hashicorp/nomad/client/structs" 10) 11 12// EmptyDuration is to be used by fingerprinters that are not periodic. 13const ( 14 EmptyDuration = time.Duration(0) 15 16 // TightenNetworkTimeoutsConfig is a config key that can be used during 17 // tests to tighten the timeouts for fingerprinters that make network calls. 18 TightenNetworkTimeoutsConfig = "test.tighten_network_timeouts" 19) 20 21func init() { 22 23 // Initialize the list of available fingerprinters per platform. Each 24 // platform defines its own list of available fingerprinters. 25 initPlatformFingerprints(hostFingerprinters) 26} 27 28var ( 29 // hostFingerprinters contains the host fingerprints which are available for a 30 // given platform. 31 hostFingerprinters = map[string]Factory{ 32 "arch": NewArchFingerprint, 33 "consul": NewConsulFingerprint, 34 "cni": NewCNIFingerprint, 35 "cpu": NewCPUFingerprint, 36 "host": NewHostFingerprint, 37 "memory": NewMemoryFingerprint, 38 "network": NewNetworkFingerprint, 39 "nomad": NewNomadFingerprint, 40 "signal": NewSignalFingerprint, 41 "storage": NewStorageFingerprint, 42 "vault": NewVaultFingerprint, 43 } 44 45 // envFingerprinters contains the fingerprints that are environment specific. 46 // This should run after the host fingerprinters as they may override specific 47 // node resources with more detailed information. 48 envFingerprinters = map[string]Factory{ 49 "env_aws": NewEnvAWSFingerprint, 50 "env_gce": NewEnvGCEFingerprint, 51 "env_azure": NewEnvAzureFingerprint, 52 } 53) 54 55// BuiltinFingerprints is a slice containing the key names of all registered 56// fingerprints available. The order of this slice should be preserved when 57// fingerprinting. 58func BuiltinFingerprints() []string { 59 fingerprints := make([]string, 0, len(hostFingerprinters)) 60 for k := range hostFingerprinters { 61 fingerprints = append(fingerprints, k) 62 } 63 sort.Strings(fingerprints) 64 for k := range envFingerprinters { 65 fingerprints = append(fingerprints, k) 66 } 67 return fingerprints 68} 69 70// NewFingerprint is used to instantiate and return a new fingerprint 71// given the name and a logger 72func NewFingerprint(name string, logger log.Logger) (Fingerprint, error) { 73 // Lookup the factory function 74 factory, ok := hostFingerprinters[name] 75 if !ok { 76 factory, ok = envFingerprinters[name] 77 if !ok { 78 return nil, fmt.Errorf("unknown fingerprint '%s'", name) 79 } 80 } 81 82 // Instantiate the fingerprint 83 f := factory(logger) 84 return f, nil 85} 86 87// Factory is used to instantiate a new Fingerprint 88type Factory func(log.Logger) Fingerprint 89 90// HealthCheck is used for doing periodic health checks. On a given time 91// interfal, a health check will be called by the fingerprint manager of the 92// node. 93type HealthCheck interface { 94 // Check is used to update properties of the node on the status of the health 95 // check 96 HealthCheck(*cstructs.HealthCheckRequest, *cstructs.HealthCheckResponse) error 97 98 // GetHealthCheckInterval is a mechanism for the health checker to indicate that 99 // it should be run periodically. The return value is a boolean indicating 100 // whether it should be done periodically, and the time interval at which 101 // this check should happen. 102 GetHealthCheckInterval(*cstructs.HealthCheckIntervalRequest, *cstructs.HealthCheckIntervalResponse) error 103} 104 105// Fingerprint is used for doing "fingerprinting" of the 106// host to automatically determine attributes, resources, 107// and metadata about it. Each of these is a heuristic, and 108// many of them can be applied on a particular host. 109type Fingerprint interface { 110 // Fingerprint is used to update properties of the Node, 111 // and returns a diff of updated node attributes and a potential error. 112 Fingerprint(*FingerprintRequest, *FingerprintResponse) error 113 114 // Periodic is a mechanism for the fingerprinter to indicate that it should 115 // be run periodically. The return value is a boolean indicating if it 116 // should be periodic, and if true, a duration. 117 Periodic() (bool, time.Duration) 118} 119 120// ReloadableFingerprint can be implemented if the fingerprinter needs to be run during client reload. 121// If implemented, the client will call Reload during client reload then immediately Fingerprint 122type ReloadableFingerprint interface { 123 Fingerprint 124 Reload() 125} 126 127// StaticFingerprinter can be embedded in a struct that has a Fingerprint method 128// to make it non-periodic. 129type StaticFingerprinter struct{} 130 131func (s *StaticFingerprinter) Periodic() (bool, time.Duration) { 132 return false, EmptyDuration 133} 134