/scrutiny/config/collector.yaml Adding ability to specify host identifier (label), that is updated on every collector run. Can be specified by `host-id` CLI or `COLLECTOR_HOST_ID` env var. Created a config class, interface and associated tests. Created a "TransformDetectedDrives" function, that will allow users to insert drives not detected by Smarctl --scan, ignore drives that they dont want, and override smartctl device type. Added Upsert functionality when registering devices. Replaced "github.com/jinzhu/gorm" with "gorm.io/gorm" (ORM location moved, was using incorrect lib url) Removed machineid library.pull/88/head
parent
32e7044c67
commit
b44ef5cb9c
@ -0,0 +1,100 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/analogj/go-util/utils"
|
||||
"github.com/analogj/scrutiny/collector/pkg/errors"
|
||||
"github.com/analogj/scrutiny/collector/pkg/models"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/spf13/viper"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// When initializing this class the following methods must be called:
|
||||
// Config.New
|
||||
// Config.Init
|
||||
// This is done automatically when created via the Factory.
|
||||
type configuration struct {
|
||||
*viper.Viper
|
||||
}
|
||||
|
||||
//Viper uses the following precedence order. Each item takes precedence over the item below it:
|
||||
// explicit call to Set
|
||||
// flag
|
||||
// env
|
||||
// config
|
||||
// key/value store
|
||||
// default
|
||||
|
||||
func (c *configuration) Init() error {
|
||||
c.Viper = viper.New()
|
||||
//set defaults
|
||||
c.SetDefault("host.id", "")
|
||||
|
||||
c.SetDefault("devices", []string{})
|
||||
|
||||
//c.SetDefault("collect.short.command", "-a -o on -S on")
|
||||
|
||||
//if you want to load a non-standard location system config file (~/drawbridge.yml), use ReadConfig
|
||||
c.SetConfigType("yaml")
|
||||
//c.SetConfigName("drawbridge")
|
||||
//c.AddConfigPath("$HOME/")
|
||||
|
||||
//CLI options will be added via the `Set()` function
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *configuration) ReadConfig(configFilePath string) error {
|
||||
configFilePath, err := utils.ExpandPath(configFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !utils.FileExists(configFilePath) {
|
||||
log.Printf("No configuration file found at %v. Using Defaults.", configFilePath)
|
||||
return errors.ConfigFileMissingError("The configuration file could not be found.")
|
||||
}
|
||||
|
||||
//validate config file contents
|
||||
//err = c.ValidateConfigFile(configFilePath)
|
||||
//if err != nil {
|
||||
// log.Printf("Config file at `%v` is invalid: %s", configFilePath, err)
|
||||
// return err
|
||||
//}
|
||||
|
||||
log.Printf("Loading configuration file: %s", configFilePath)
|
||||
|
||||
config_data, err := os.Open(configFilePath)
|
||||
if err != nil {
|
||||
log.Printf("Error reading configuration file: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MergeConfig(config_data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.ValidateConfig()
|
||||
}
|
||||
|
||||
// This function ensures that the merged config works correctly.
|
||||
func (c *configuration) ValidateConfig() error {
|
||||
|
||||
//TODO:
|
||||
// check that device prefix matches OS
|
||||
// check that schema of config file is valid
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *configuration) GetScanOverrides() []models.ScanOverride {
|
||||
// we have to support 2 types of device types.
|
||||
// - simple device type (device_type: 'sat')
|
||||
// and list of device types (type: \n- 3ware,0 \n- 3ware,1 \n- 3ware,2)
|
||||
// GetString will return "" if this is a list of device types.
|
||||
|
||||
overrides := []models.ScanOverride{}
|
||||
c.UnmarshalKey("devices", &overrides, func(c *mapstructure.DecoderConfig) { c.WeaklyTypedInput = true })
|
||||
return overrides
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"github.com/analogj/scrutiny/collector/pkg/config"
|
||||
"github.com/analogj/scrutiny/collector/pkg/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
"path"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfiguration_GetScanOverrides_Simple(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//setup
|
||||
testConfig, _ := config.Create()
|
||||
|
||||
//test
|
||||
err := testConfig.ReadConfig(path.Join("testdata", "simple_device.yaml"))
|
||||
require.NoError(t, err, "should correctly load simple device config")
|
||||
scanOverrides := testConfig.GetScanOverrides()
|
||||
|
||||
//assert
|
||||
require.Equal(t, []models.ScanOverride{{Device: "/dev/sda", DeviceType: []string{"sat"}, Ignore: false}}, scanOverrides)
|
||||
}
|
||||
|
||||
func TestConfiguration_GetScanOverrides_Ignore(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//setup
|
||||
testConfig, _ := config.Create()
|
||||
|
||||
//test
|
||||
err := testConfig.ReadConfig(path.Join("testdata", "ignore_device.yaml"))
|
||||
require.NoError(t, err, "should correctly load ignore device config")
|
||||
scanOverrides := testConfig.GetScanOverrides()
|
||||
|
||||
//assert
|
||||
require.Equal(t, []models.ScanOverride{{Device: "/dev/sda", DeviceType: nil, Ignore: true}}, scanOverrides)
|
||||
}
|
||||
|
||||
func TestConfiguration_GetScanOverrides_Raid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//setup
|
||||
testConfig, _ := config.Create()
|
||||
|
||||
//test
|
||||
err := testConfig.ReadConfig(path.Join("testdata", "raid_device.yaml"))
|
||||
require.NoError(t, err, "should correctly load ignore device config")
|
||||
scanOverrides := testConfig.GetScanOverrides()
|
||||
|
||||
//assert
|
||||
require.Equal(t, []models.ScanOverride{
|
||||
{
|
||||
Device: "/dev/bus/0",
|
||||
DeviceType: []string{"megaraid,14", "megaraid,15", "megaraid,18", "megaraid,19", "megaraid,20", "megaraid,21"},
|
||||
Ignore: false,
|
||||
},
|
||||
{
|
||||
Device: "/dev/twa0",
|
||||
DeviceType: []string{"3ware,0", "3ware,1", "3ware,2", "3ware,3", "3ware,4", "3ware,5"},
|
||||
Ignore: false,
|
||||
}}, scanOverrides)
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
func Create() (Interface, error) {
|
||||
config := new(configuration)
|
||||
if err := config.Init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/analogj/scrutiny/collector/pkg/models"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Create mock using:
|
||||
// mockgen -source=collector/pkg/config/interface.go -destination=collector/pkg/config/mock/mock_config.go
|
||||
type Interface interface {
|
||||
Init() error
|
||||
ReadConfig(configFilePath string) error
|
||||
Set(key string, value interface{})
|
||||
SetDefault(key string, value interface{})
|
||||
|
||||
AllSettings() map[string]interface{}
|
||||
IsSet(key string) bool
|
||||
Get(key string) interface{}
|
||||
GetBool(key string) bool
|
||||
GetInt(key string) int
|
||||
GetString(key string) string
|
||||
GetStringSlice(key string) []string
|
||||
UnmarshalKey(key string, rawVal interface{}, decoderOpts ...viper.DecoderConfigOption) error
|
||||
|
||||
GetScanOverrides() []models.ScanOverride
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: collector/pkg/config/interface.go
|
||||
|
||||
// Package mock_config is a generated GoMock package.
|
||||
package mock_config
|
||||
|
||||
import (
|
||||
models "github.com/analogj/scrutiny/collector/pkg/models"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
viper "github.com/spf13/viper"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockInterface is a mock of Interface interface
|
||||
type MockInterface struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockInterfaceMockRecorder
|
||||
}
|
||||
|
||||
// MockInterfaceMockRecorder is the mock recorder for MockInterface
|
||||
type MockInterfaceMockRecorder struct {
|
||||
mock *MockInterface
|
||||
}
|
||||
|
||||
// NewMockInterface creates a new mock instance
|
||||
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
|
||||
mock := &MockInterface{ctrl: ctrl}
|
||||
mock.recorder = &MockInterfaceMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Init mocks base method
|
||||
func (m *MockInterface) Init() error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Init")
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Init indicates an expected call of Init
|
||||
func (mr *MockInterfaceMockRecorder) Init() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockInterface)(nil).Init))
|
||||
}
|
||||
|
||||
// ReadConfig mocks base method
|
||||
func (m *MockInterface) ReadConfig(configFilePath string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ReadConfig", configFilePath)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ReadConfig indicates an expected call of ReadConfig
|
||||
func (mr *MockInterfaceMockRecorder) ReadConfig(configFilePath interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadConfig", reflect.TypeOf((*MockInterface)(nil).ReadConfig), configFilePath)
|
||||
}
|
||||
|
||||
// Set mocks base method
|
||||
func (m *MockInterface) Set(key string, value interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Set", key, value)
|
||||
}
|
||||
|
||||
// Set indicates an expected call of Set
|
||||
func (mr *MockInterfaceMockRecorder) Set(key, value interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockInterface)(nil).Set), key, value)
|
||||
}
|
||||
|
||||
// SetDefault mocks base method
|
||||
func (m *MockInterface) SetDefault(key string, value interface{}) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetDefault", key, value)
|
||||
}
|
||||
|
||||
// SetDefault indicates an expected call of SetDefault
|
||||
func (mr *MockInterfaceMockRecorder) SetDefault(key, value interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDefault", reflect.TypeOf((*MockInterface)(nil).SetDefault), key, value)
|
||||
}
|
||||
|
||||
// AllSettings mocks base method
|
||||
func (m *MockInterface) AllSettings() map[string]interface{} {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AllSettings")
|
||||
ret0, _ := ret[0].(map[string]interface{})
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AllSettings indicates an expected call of AllSettings
|
||||
func (mr *MockInterfaceMockRecorder) AllSettings() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllSettings", reflect.TypeOf((*MockInterface)(nil).AllSettings))
|
||||
}
|
||||
|
||||
// IsSet mocks base method
|
||||
func (m *MockInterface) IsSet(key string) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsSet", key)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsSet indicates an expected call of IsSet
|
||||
func (mr *MockInterfaceMockRecorder) IsSet(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSet", reflect.TypeOf((*MockInterface)(nil).IsSet), key)
|
||||
}
|
||||
|
||||
// Get mocks base method
|
||||
func (m *MockInterface) Get(key string) interface{} {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", key)
|
||||
ret0, _ := ret[0].(interface{})
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get
|
||||
func (mr *MockInterfaceMockRecorder) Get(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), key)
|
||||
}
|
||||
|
||||
// GetBool mocks base method
|
||||
func (m *MockInterface) GetBool(key string) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBool", key)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetBool indicates an expected call of GetBool
|
||||
func (mr *MockInterfaceMockRecorder) GetBool(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBool", reflect.TypeOf((*MockInterface)(nil).GetBool), key)
|
||||
}
|
||||
|
||||
// GetInt mocks base method
|
||||
func (m *MockInterface) GetInt(key string) int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetInt", key)
|
||||
ret0, _ := ret[0].(int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetInt indicates an expected call of GetInt
|
||||
func (mr *MockInterfaceMockRecorder) GetInt(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInt", reflect.TypeOf((*MockInterface)(nil).GetInt), key)
|
||||
}
|
||||
|
||||
// GetString mocks base method
|
||||
func (m *MockInterface) GetString(key string) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetString", key)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetString indicates an expected call of GetString
|
||||
func (mr *MockInterfaceMockRecorder) GetString(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetString", reflect.TypeOf((*MockInterface)(nil).GetString), key)
|
||||
}
|
||||
|
||||
// GetStringSlice mocks base method
|
||||
func (m *MockInterface) GetStringSlice(key string) []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetStringSlice", key)
|
||||
ret0, _ := ret[0].([]string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetStringSlice indicates an expected call of GetStringSlice
|
||||
func (mr *MockInterfaceMockRecorder) GetStringSlice(key interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStringSlice", reflect.TypeOf((*MockInterface)(nil).GetStringSlice), key)
|
||||
}
|
||||
|
||||
// UnmarshalKey mocks base method
|
||||
func (m *MockInterface) UnmarshalKey(key string, rawVal interface{}, decoderOpts ...viper.DecoderConfigOption) error {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{key, rawVal}
|
||||
for _, a := range decoderOpts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "UnmarshalKey", varargs...)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnmarshalKey indicates an expected call of UnmarshalKey
|
||||
func (mr *MockInterfaceMockRecorder) UnmarshalKey(key, rawVal interface{}, decoderOpts ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{key, rawVal}, decoderOpts...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnmarshalKey", reflect.TypeOf((*MockInterface)(nil).UnmarshalKey), varargs...)
|
||||
}
|
||||
|
||||
// GetScanOverrides mocks base method
|
||||
func (m *MockInterface) GetScanOverrides() []models.ScanOverride {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetScanOverrides")
|
||||
ret0, _ := ret[0].([]models.ScanOverride)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetScanOverrides indicates an expected call of GetScanOverrides
|
||||
func (mr *MockInterfaceMockRecorder) GetScanOverrides() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetScanOverrides", reflect.TypeOf((*MockInterface)(nil).GetScanOverrides))
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
version: 1
|
||||
devices:
|
||||
- device: /dev/sda
|
||||
ignore: true
|
@ -0,0 +1,19 @@
|
||||
version: 1
|
||||
devices:
|
||||
- device: /dev/bus/0
|
||||
type:
|
||||
- megaraid,14
|
||||
- megaraid,15
|
||||
- megaraid,18
|
||||
- megaraid,19
|
||||
- megaraid,20
|
||||
- megaraid,21
|
||||
|
||||
- device: /dev/twa0
|
||||
type:
|
||||
- 3ware,0
|
||||
- 3ware,1
|
||||
- 3ware,2
|
||||
- 3ware,3
|
||||
- 3ware,4
|
||||
- 3ware,5
|
@ -0,0 +1,27 @@
|
||||
version: 1
|
||||
devices:
|
||||
- device: /dev/sda
|
||||
type: 'sat'
|
||||
#
|
||||
# # example to show how to ignore a specific disk/device.
|
||||
# - device: /dev/sda
|
||||
# ignore: true
|
||||
#
|
||||
# # examples showing how to force smartctl to detect disks inside a raid array/virtual disk
|
||||
# - device: /dev/bus/0
|
||||
# type:
|
||||
# - megaraid,14
|
||||
# - megaraid,15
|
||||
# - megaraid,18
|
||||
# - megaraid,19
|
||||
# - megaraid,20
|
||||
# - megaraid,21
|
||||
#
|
||||
# - device: /dev/twa0
|
||||
# type:
|
||||
# - 3ware,0
|
||||
# - 3ware,1
|
||||
# - 3ware,2
|
||||
# - 3ware,3
|
||||
# - 3ware,4
|
||||
# - 3ware,5
|
@ -0,0 +1,138 @@
|
||||
package detect_test
|
||||
|
||||
import (
|
||||
mock_config "github.com/analogj/scrutiny/collector/pkg/config/mock"
|
||||
"github.com/analogj/scrutiny/collector/pkg/detect"
|
||||
"github.com/analogj/scrutiny/collector/pkg/models"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDetect_TransformDetectedDevices_Empty(t *testing.T) {
|
||||
//setup
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
fakeConfig := mock_config.NewMockInterface(mockCtrl)
|
||||
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
|
||||
fakeConfig.EXPECT().GetScanOverrides().AnyTimes().Return([]models.ScanOverride{})
|
||||
detectedDevices := models.Scan{
|
||||
Devices: []models.ScanDevice{
|
||||
{
|
||||
Name: "/dev/sda",
|
||||
InfoName: "/dev/sda",
|
||||
Protocol: "scsi",
|
||||
Type: "scsi",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
d := detect.Detect{
|
||||
Config: fakeConfig,
|
||||
}
|
||||
|
||||
//test
|
||||
transformedDevices := d.TransformDetectedDevices(detectedDevices)
|
||||
|
||||
//assert
|
||||
require.Equal(t, "sda", transformedDevices[0].DeviceName)
|
||||
require.Equal(t, "scsi", transformedDevices[0].DeviceType)
|
||||
}
|
||||
|
||||
func TestDetect_TransformDetectedDevices_Ignore(t *testing.T) {
|
||||
//setup
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
fakeConfig := mock_config.NewMockInterface(mockCtrl)
|
||||
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
|
||||
fakeConfig.EXPECT().GetScanOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda", DeviceType: nil, Ignore: true}})
|
||||
detectedDevices := models.Scan{
|
||||
Devices: []models.ScanDevice{
|
||||
{
|
||||
Name: "/dev/sda",
|
||||
InfoName: "/dev/sda",
|
||||
Protocol: "scsi",
|
||||
Type: "scsi",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
d := detect.Detect{
|
||||
Config: fakeConfig,
|
||||
}
|
||||
|
||||
//test
|
||||
transformedDevices := d.TransformDetectedDevices(detectedDevices)
|
||||
|
||||
//assert
|
||||
require.Equal(t, []models.Device{}, transformedDevices)
|
||||
}
|
||||
|
||||
func TestDetect_TransformDetectedDevices_Raid(t *testing.T) {
|
||||
//setup
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
fakeConfig := mock_config.NewMockInterface(mockCtrl)
|
||||
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
|
||||
fakeConfig.EXPECT().GetScanOverrides().AnyTimes().Return([]models.ScanOverride{
|
||||
{
|
||||
Device: "/dev/bus/0",
|
||||
DeviceType: []string{"megaraid,14", "megaraid,15", "megaraid,18", "megaraid,19", "megaraid,20", "megaraid,21"},
|
||||
Ignore: false,
|
||||
},
|
||||
{
|
||||
Device: "/dev/twa0",
|
||||
DeviceType: []string{"3ware,0", "3ware,1", "3ware,2", "3ware,3", "3ware,4", "3ware,5"},
|
||||
Ignore: false,
|
||||
}})
|
||||
detectedDevices := models.Scan{
|
||||
Devices: []models.ScanDevice{
|
||||
{
|
||||
Name: "/dev/bus/0",
|
||||
InfoName: "/dev/bus/0",
|
||||
Protocol: "scsi",
|
||||
Type: "scsi",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
d := detect.Detect{
|
||||
Config: fakeConfig,
|
||||
}
|
||||
|
||||
//test
|
||||
transformedDevices := d.TransformDetectedDevices(detectedDevices)
|
||||
|
||||
//assert
|
||||
require.Equal(t, 12, len(transformedDevices))
|
||||
}
|
||||
|
||||
func TestDetect_TransformDetectedDevices_Simple(t *testing.T) {
|
||||
//setup
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
fakeConfig := mock_config.NewMockInterface(mockCtrl)
|
||||
fakeConfig.EXPECT().GetString("host.id").AnyTimes().Return("")
|
||||
fakeConfig.EXPECT().GetScanOverrides().AnyTimes().Return([]models.ScanOverride{{Device: "/dev/sda", DeviceType: []string{"sat+megaraid"}}})
|
||||
detectedDevices := models.Scan{
|
||||
Devices: []models.ScanDevice{
|
||||
{
|
||||
Name: "/dev/sda",
|
||||
InfoName: "/dev/sda",
|
||||
Protocol: "ata",
|
||||
Type: "ata",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
d := detect.Detect{
|
||||
Config: fakeConfig,
|
||||
}
|
||||
|
||||
//test
|
||||
transformedDevices := d.TransformDetectedDevices(detectedDevices)
|
||||
|
||||
//assert
|
||||
require.Equal(t, 1, len(transformedDevices))
|
||||
require.Equal(t, "sat+megaraid", transformedDevices[0].DeviceType)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package models
|
||||
|
||||
type ScanOverride struct {
|
||||
Device string `mapstructure:"device"`
|
||||
DeviceType []string `mapstructure:"type"`
|
||||
Ignore bool `mapstructure:"ignore"`
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
# Commented Scrutiny Configuration File
|
||||
#
|
||||
# The default location for this file is /scrutiny/config/collector.yaml.
|
||||
# In some cases to improve clarity default values are specified,
|
||||
# uncommented. Other example values are commented out.
|
||||
#
|
||||
# When this file is parsed by Scrutiny, all configuration file keys are
|
||||
# lowercased automatically. As such, Configuration keys are case-insensitive,
|
||||
# and should be lowercase in this file to be consistent with usage.
|
||||
|
||||
|
||||
######################################################################
|
||||
# Version
|
||||
#
|
||||
# version specifies the version of this configuration file schema, not
|
||||
# the scrutiny binary. There is only 1 version available at the moment
|
||||
version: 1
|
||||
|
||||
# The host id is a label used for identifying groups of disks running on the same host
|
||||
# Primiarly used for hub/spoke deployments (can be left empty if using all-in-one image).
|
||||
host:
|
||||
id: ""
|
||||
|
||||
|
||||
# This block allows you to override/customize the settings for devices detected by
|
||||
# Scrutiny via `smartctl --scan`
|
||||
# See the "--device=TYPE" section of https://linux.die.net/man/8/smartctl
|
||||
# type can be a 'string' or a 'list'
|
||||
devices:
|
||||
# # example for forcing device type detection for a single disk
|
||||
# - device: /dev/sda
|
||||
# type: 'sat'
|
||||
#
|
||||
# # example to show how to ignore a specific disk/device.
|
||||
# - device: /dev/sda
|
||||
# ignore: true
|
||||
#
|
||||
# # examples showing how to force smartctl to detect disks inside a raid array/virtual disk
|
||||
# - device: /dev/bus/0
|
||||
# type:
|
||||
# - megaraid,14
|
||||
# - megaraid,15
|
||||
# - megaraid,18
|
||||
# - megaraid,19
|
||||
# - megaraid,20
|
||||
# - megaraid,21
|
||||
#
|
||||
# - device: /dev/twa0
|
||||
# type:
|
||||
# - 3ware,0
|
||||
# - 3ware,1
|
||||
# - 3ware,2
|
||||
# - 3ware,3
|
||||
# - 3ware,4
|
||||
# - 3ware,5
|
||||
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# FEATURES COMING SOON
|
||||
#
|
||||
# The following commented out sections are a preview of additional configuration options that will be available soon.
|
||||
#
|
||||
########################################################################################################################
|
||||
|
Loading…
Reference in new issue