refactor into multiple fingerprints

This commit is contained in:
Clint Shryock 2015-08-26 16:27:44 -05:00
parent 8ab31da8b0
commit 9a92383b69
8 changed files with 159 additions and 61 deletions

View file

@ -0,0 +1,10 @@
package fingerprint
import (
"log"
"os"
)
func testLogger() *log.Logger {
return log.New(os.Stderr, "", log.LstdFlags)
}

51
client/fingerprint/cpu.go Normal file
View file

@ -0,0 +1,51 @@
package fingerprint
import (
"log"
"strconv"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shirou/gopsutil/cpu"
)
// CPUFingerprint is used to fingerprint the CPU
type CPUFingerprint struct {
logger *log.Logger
}
// NewCPUFingerprint is used to create a CPU fingerprint
func NewCPUFingerprint(logger *log.Logger) Fingerprint {
f := &CPUFingerprint{logger}
return f
}
func (f *CPUFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
cpuInfo, err := cpu.CPUInfo()
if err != nil {
f.logger.Println("[WARN] Error reading CPU information:", err)
return false, err
}
var numCores int32
numCores = 0
var modelName string
// Assume all CPUs found have same Model. Log if not.
// If CPUInfo() returns nil above, this loop is still safe
for i, c := range cpuInfo {
f.logger.Printf("(%d) Vendor: %s", i, c.VendorID)
numCores += c.Cores
if modelName != "" && modelName != c.ModelName {
f.logger.Println("[WARN] Found different model names in the same CPU information. Recording last found")
}
modelName = c.ModelName
}
if numCores > 0 {
node.Attributes["cpu.numcores"] = strconv.FormatInt(int64(numCores), 10)
}
if modelName != "" {
node.Attributes["cpu.modelname"] = modelName
}
return true, nil
}

View file

@ -0,0 +1,31 @@
package fingerprint
import (
"testing"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs"
)
func TestCPUFingerprint(t *testing.T) {
f := NewCPUFingerprint(testLogger())
node := &structs.Node{
Attributes: make(map[string]string),
}
ok, err := f.Fingerprint(&config.Config{}, node)
if err != nil {
t.Fatalf("err: %v", err)
}
if !ok {
t.Fatalf("should apply")
}
// CPU info
if node.Attributes["cpu.numcores"] == "" {
t.Fatalf("Missing Num Cores")
}
if node.Attributes["cpu.modelname"] == "" {
t.Fatalf("Missing Model Name")
}
}

View file

@ -11,8 +11,10 @@ import (
// BuiltinFingerprints contains the built in registered fingerprints // BuiltinFingerprints contains the built in registered fingerprints
// which are available // which are available
var BuiltinFingerprints = map[string]Factory{ var BuiltinFingerprints = map[string]Factory{
"os": NewOSFingerprint,
"arch": NewArchFingerprint, "arch": NewArchFingerprint,
"cpu": NewCPUFingerprint,
"host": NewHostFingerprint,
"os": NewOSFingerprint,
} }
// NewFingerprint is used to instantiate and return a new fingerprint // NewFingerprint is used to instantiate and return a new fingerprint

View file

@ -0,0 +1,35 @@
package fingerprint
import (
"log"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shirou/gopsutil/host"
)
// HostFingerprint is used to fingerprint the host
type HostFingerprint struct {
logger *log.Logger
}
// NewHostFingerprint is used to create a Host fingerprint
func NewHostFingerprint(logger *log.Logger) Fingerprint {
f := &HostFingerprint{logger}
return f
}
func (f *HostFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
hostInfo, err := host.HostInfo()
if err != nil {
f.logger.Println("[WARN] Error retrieving host information: ", err)
return false, err
}
node.Attributes["os.name"] = hostInfo.Platform
node.Attributes["os.version"] = hostInfo.PlatformVersion
node.Attributes["hostname"] = hostInfo.Hostname
node.Attributes["kernel.name"] = hostInfo.OS
return true, nil
}

View file

@ -0,0 +1,29 @@
package fingerprint
import (
"testing"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs"
)
func TestHostFingerprint(t *testing.T) {
f := NewHostFingerprint(testLogger())
node := &structs.Node{
Attributes: make(map[string]string),
}
ok, err := f.Fingerprint(&config.Config{}, node)
if err != nil {
t.Fatalf("err: %v", err)
}
if !ok {
t.Fatalf("should apply")
}
// Host info
for _, key := range []string{"os.name", "os.version", "hostname", "kernel.name"} {
if node.Attributes[key] == "" {
t.Fatalf("Missing (%s) in Host Info attribute check", key)
}
}
}

View file

@ -3,12 +3,9 @@ package fingerprint
import ( import (
"log" "log"
"runtime" "runtime"
"strconv"
"github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/host"
) )
// OSFingerprint is used to fingerprint the operating system // OSFingerprint is used to fingerprint the operating system
@ -26,42 +23,5 @@ func (f *OSFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (boo
node.Attributes["os"] = runtime.GOOS node.Attributes["os"] = runtime.GOOS
f.logger.Printf("[DEBUG] fingerprint.os: detected '%s'", runtime.GOOS) f.logger.Printf("[DEBUG] fingerprint.os: detected '%s'", runtime.GOOS)
cpuInfo, err := cpu.CPUInfo()
if err != nil {
f.logger.Println("[WARN] Error reading CPU information:", err)
}
var numCores int32
numCores = 0
var modelName string
// Assume all CPUs found have same Model. Log if not.
// If CPUInfo() returns err above, this loop is still safe
for i, c := range cpuInfo {
f.logger.Printf("(%d) Vendor: %s", i, c.VendorID)
numCores += c.Cores
if modelName != "" && modelName != c.ModelName {
f.logger.Println("[WARN] Found different model names in the same CPU information. Recording last found")
}
modelName = c.ModelName
}
if numCores > 0 {
node.Attributes["cpu.numcores"] = strconv.FormatInt(int64(numCores), 10)
}
if modelName != "" {
node.Attributes["cpu.modelname"] = modelName
}
hostInfo, err := host.HostInfo()
if err != nil {
f.logger.Println("[WARN] Error retrieving host information: ", err)
} else {
node.Attributes["os.name"] = hostInfo.Platform
node.Attributes["os.version"] = hostInfo.PlatformVersion
node.Attributes["hostname"] = hostInfo.Hostname
node.Attributes["kernel.name"] = hostInfo.OS
}
f.logger.Printf("Node: %s", node)
return true, nil return true, nil
} }

View file

@ -1,18 +1,12 @@
package fingerprint package fingerprint
import ( import (
"log"
"os"
"testing" "testing"
"github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
) )
func testLogger() *log.Logger {
return log.New(os.Stderr, "", log.LstdFlags)
}
func TestOSFingerprint(t *testing.T) { func TestOSFingerprint(t *testing.T) {
f := NewOSFingerprint(testLogger()) f := NewOSFingerprint(testLogger())
node := &structs.Node{ node := &structs.Node{
@ -31,18 +25,4 @@ func TestOSFingerprint(t *testing.T) {
t.Fatalf("missing OS") t.Fatalf("missing OS")
} }
// CPU info
if node.Attributes["cpu.numcores"] == "" {
t.Fatalf("Missing Num Cores")
}
if node.Attributes["cpu.modelname"] == "" {
t.Fatalf("Missing Model Name")
}
// Host info
for _, key := range []string{"os.name", "os.version", "hostname", "kernel.name"} {
if node.Attributes[key] == "" {
t.Fatalf("Missing (%s) in Host Info attribute check", key)
}
}
} }