github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/fingerprint/fingerprint.go (about)

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