diff --git a/collector/redfish_collector.go b/collector/redfish_collector.go index 0e6ad48..3b659b1 100755 --- a/collector/redfish_collector.go +++ b/collector/redfish_collector.go @@ -2,11 +2,14 @@ package collector import ( "bytes" + "crypto/tls" "fmt" + "net/http" "sync" "time" "github.com/apex/log" + "github.com/jenningsloy318/redfish_exporter/config" "github.com/prometheus/client_golang/prometheus" gofish "github.com/stmcginnis/gofish" gofishcommon "github.com/stmcginnis/gofish/common" @@ -40,12 +43,14 @@ type RedfishCollector struct { } // NewRedfishCollector return RedfishCollector -func NewRedfishCollector(host string, username string, password string, logger *log.Entry) *RedfishCollector { +func NewRedfishCollector(targetHostConfig *config.HostConfig, logger *log.Entry) *RedfishCollector { var collectors map[string]prometheus.Collector collectorLogCtx := logger - redfishClient, err := newRedfishClient(host, username, password) + + redfishClient, err := newRedfishClient(targetHostConfig) + if err != nil { - collectorLogCtx.WithError(err).Error("error creating redfish client") + collectorLogCtx.WithError(err).Error("error creating redfish client for target host") } else { chassisCollector := NewChassisCollector(namespace, redfishClient, collectorLogCtx) systemCollector := NewSystemCollector(namespace, redfishClient, collectorLogCtx) @@ -101,16 +106,22 @@ func (r *RedfishCollector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(totalScrapeDurationDesc, prometheus.GaugeValue, time.Since(scrapeTime).Seconds()) } -func newRedfishClient(host string, username string, password string) (*gofish.APIClient, error) { +func newRedfishClient(targetHostConfig *config.HostConfig) (*gofish.APIClient, error) { - url := fmt.Sprintf("https://%s", host) + url := fmt.Sprintf("https://%s", targetHostConfig.Host) config := gofish.ClientConfig{ Endpoint: url, - Username: username, - Password: password, - Insecure: true, + Username: targetHostConfig.Username, + Password: targetHostConfig.Password, + HTTPClient: &http.Client{ + Timeout: time.Duration(targetHostConfig.Timeout) * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: targetHostConfig.Insecure}, + }, + }, } + redfishClient, err := gofish.Connect(config) if err != nil { return nil, err diff --git a/config.go b/config.go deleted file mode 100755 index 501649f..0000000 --- a/config.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "regexp" - "sync" - - yaml "gopkg.in/yaml.v2" -) - -type Config struct { - Hosts map[string]HostConfig `yaml:"hosts"` -} - -type SafeConfig struct { - sync.RWMutex - Config *Config -} - -type HostConfig struct { - Username string `yaml:"username"` - Password string `yaml:"password"` -} - -func (sc *SafeConfig) ReloadConfig(configFile string) error { - var c = &Config{} - - yamlFile, err := ioutil.ReadFile(configFile) - if err != nil { - return err - } - if err := yaml.Unmarshal(yamlFile, c); err != nil { - return err - } - - sc.Lock() - sc.Config = c - sc.Unlock() - - return nil -} - -func (sc *SafeConfig) HostConfigForTarget(target string) (*HostConfig, error) { - sc.Lock() - defer sc.Unlock() - - for host, account := range sc.Config.Hosts { - match, _ := regexp.MatchString(host, target) - if match { - return &HostConfig{ - Username: account.Username, - Password: account.Password, - }, nil - } - } - // if no match found, fallback to default - if hostConfig, ok := sc.Config.Hosts["default"]; ok { - return &HostConfig{ - Username: hostConfig.Username, - Password: hostConfig.Password, - }, nil - } - - // if no default specified, exit with an error - return &HostConfig{}, fmt.Errorf("no credentials found for target %s", target) -} diff --git a/config/config.go b/config/config.go new file mode 100755 index 0000000..cd5e6fa --- /dev/null +++ b/config/config.go @@ -0,0 +1,80 @@ +package config + +import ( + "fmt" + "io/ioutil" + "regexp" + "sync" + + yaml "gopkg.in/yaml.v2" +) + +//Config is the struct that represents config.yml +type Config struct { + Timeout int32 `yaml:"timeout"` + Insecure bool `yaml:"insecure"` + Port int32 `yaml:"port"` + Hosts map[string]HostConfig `yaml:"hosts"` +} + +type SafeConfig struct { + sync.RWMutex + Config *Config +} + +//HostConfig is the struct that is passed to the redfish client +type HostConfig struct { + Host string + Username string + Password string + Timeout int32 + Insecure bool +} + +func (sc *SafeConfig) ReloadConfig(configFile string) error { + var c = &Config{} + + yamlFile, err := ioutil.ReadFile(configFile) + if err != nil { + return err + } + if err := yaml.Unmarshal(yamlFile, c); err != nil { + return err + } + + sc.Lock() + sc.Config = c + sc.Unlock() + + return nil +} + +func (sc *SafeConfig) HostConfigForTarget(targetHost string) (*HostConfig, error) { + sc.Lock() + defer sc.Unlock() + + targetHostConfig := &HostConfig{ + Host: targetHost, + Timeout: sc.Config.Timeout, + Insecure: sc.Config.Insecure, + } + + // search for host that matches the target + for host, account := range sc.Config.Hosts { + match, _ := regexp.MatchString(host, targetHost) + if match { + targetHostConfig.Username = account.Username + targetHostConfig.Password = account.Password + return targetHostConfig, nil + } + } + // if no match found, fallback to default + if hostConfig, ok := sc.Config.Hosts["default"]; ok { + targetHostConfig.Username = hostConfig.Username + targetHostConfig.Password = hostConfig.Password + return targetHostConfig, nil + } + + // if no default specified, exit with an error + return &HostConfig{}, fmt.Errorf("no credentials found for target %s", targetHost) +} diff --git a/go.mod b/go.mod index cce7e2a..975cee2 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/apex/log v1.9.0 github.com/prometheus/client_golang v1.1.0 github.com/prometheus/common v0.6.0 - github.com/stmcginnis/gofish v0.4.1-0.20200604221848-686ec78d313a + github.com/stmcginnis/gofish v0.5.0 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 2de5ca0..84a9a01 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= -github.com/stmcginnis/gofish v0.4.1-0.20200604221848-686ec78d313a h1:htamKApX77urNAThHwI56sTyhLNHp1TBRsFZDt+p/G8= -github.com/stmcginnis/gofish v0.4.1-0.20200604221848-686ec78d313a/go.mod h1:t0RUeoOLznx9vExQOeLZUrjU0u3yy0wL4iVMQviUl+k= +github.com/stmcginnis/gofish v0.5.0 h1:hD8ji0I6G6wFEe59l03Bk1u8izgj4agR0S+Hvnp4wws= +github.com/stmcginnis/gofish v0.5.0/go.mod h1:t0RUeoOLznx9vExQOeLZUrjU0u3yy0wL4iVMQviUl+k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/main.go b/main.go index c91c58b..8f64204 100755 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( alog "github.com/apex/log" "github.com/jenningsloy318/redfish_exporter/collector" + "github.com/jenningsloy318/redfish_exporter/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/log" @@ -30,9 +31,11 @@ var ( "web.listen-address", "Address to listen on for web interface and telemetry.", ).Default(":9610").String() - sc = &SafeConfig{ - Config: &Config{}, + + sc = &config.SafeConfig{ + Config: &config.Config{}, } + reloadCh chan chan error ) @@ -57,15 +60,15 @@ func metricsHandler() http.HandlerFunc { targetLoggerCtx := rootLoggerCtx.WithField("target", target) targetLoggerCtx.Info("scraping target host") - var hostConfig *HostConfig + var targetHostConfig *config.HostConfig var err error - if hostConfig, err = sc.HostConfigForTarget(target); err != nil { + if targetHostConfig, err = sc.HostConfigForTarget(target); err != nil { targetLoggerCtx.WithError(err).Error("error getting credentials") return } - collector := collector.NewRedfishCollector(target, hostConfig.Username, hostConfig.Password, targetLoggerCtx) + collector := collector.NewRedfishCollector(targetHostConfig, targetLoggerCtx) registry.MustRegister(collector) gatherers := prometheus.Gatherers{ prometheus.DefaultGatherer,