feat: Add config file validation (#2011)

This commit is contained in:
Jan-Otto Kröpke
2025-04-24 23:45:21 +02:00
committed by GitHub
parent 554607fee2
commit 769363d157
25 changed files with 107 additions and 66 deletions

View File

@@ -19,6 +19,7 @@ linters:
- maintidx
- mnd
- paralleltest
- tagliatelle
- testpackage
- varnamelen
- wrapcheck

View File

@@ -34,7 +34,7 @@ import (
const Name = "dfsr"
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"sources-enabled"`
}
//nolint:gochecknoglobals

View File

@@ -41,7 +41,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -38,7 +38,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -46,7 +46,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -35,7 +35,7 @@ import (
const Name = "filetime"
type Config struct {
FilePatterns []string
FilePatterns []string `yaml:"file-patterns"`
}
//nolint:gochecknoglobals

View File

@@ -52,7 +52,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -35,10 +35,10 @@ import (
const Name = "iis"
type Config struct {
SiteInclude *regexp.Regexp `yaml:"site_include"`
SiteExclude *regexp.Regexp `yaml:"site_exclude"`
AppInclude *regexp.Regexp `yaml:"app_include"`
AppExclude *regexp.Regexp `yaml:"app_exclude"`
SiteInclude *regexp.Regexp `yaml:"site-include"`
SiteExclude *regexp.Regexp `yaml:"site-exclude"`
AppInclude *regexp.Regexp `yaml:"app-include"`
AppExclude *regexp.Regexp `yaml:"app-exclude"`
}
//nolint:gochecknoglobals

View File

@@ -38,8 +38,8 @@ import (
const Name = "logical_disk"
type Config struct {
VolumeInclude *regexp.Regexp `yaml:"volume_include"`
VolumeExclude *regexp.Regexp `yaml:"volume_exclude"`
VolumeInclude *regexp.Regexp `yaml:"volume-include"`
VolumeExclude *regexp.Regexp `yaml:"volume-exclude"`
}
//nolint:gochecknoglobals

View File

@@ -41,7 +41,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -54,7 +54,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -43,9 +43,9 @@ const (
)
type Config struct {
NicExclude *regexp.Regexp `yaml:"nic_exclude"`
NicInclude *regexp.Regexp `yaml:"nic_include"`
CollectorsEnabled []string `yaml:"collectors_enabled"`
NicExclude *regexp.Regexp `yaml:"nic-exclude"`
NicInclude *regexp.Regexp `yaml:"nic-include"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -33,7 +33,7 @@ import (
const Name = "netframework"
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -19,6 +19,7 @@ package performancecounter
import (
"github.com/prometheus-community/windows_exporter/internal/pdh"
"gopkg.in/yaml.v3"
)
type Object struct {
@@ -41,3 +42,7 @@ type Counter struct {
}
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/54691ebe11bb9ec32b4e35cd31fcb94a352de134/receiver/windowsperfcountersreceiver/README.md?plain=1#L150
func (*Config) UnmarshalYAML(*yaml.Node) error {
return nil
}

View File

@@ -33,8 +33,8 @@ import (
const Name = "physical_disk"
type Config struct {
DiskInclude *regexp.Regexp `yaml:"disk_include"`
DiskExclude *regexp.Regexp `yaml:"disk_exclude"`
DiskInclude *regexp.Regexp `yaml:"disk-include"`
DiskExclude *regexp.Regexp `yaml:"disk-exclude"`
}
//nolint:gochecknoglobals

View File

@@ -46,8 +46,8 @@ var printerStatusMap = map[uint16]string{
}
type Config struct {
PrinterInclude *regexp.Regexp `yaml:"printer_include"`
PrinterExclude *regexp.Regexp `yaml:"printer_exclude"`
PrinterInclude *regexp.Regexp `yaml:"include"`
PrinterExclude *regexp.Regexp `yaml:"exclude"`
}
//nolint:gochecknoglobals

View File

@@ -39,9 +39,9 @@ import (
const Name = "process"
type Config struct {
ProcessInclude *regexp.Regexp `yaml:"process_include"`
ProcessExclude *regexp.Regexp `yaml:"process_exclude"`
EnableWorkerProcess bool `yaml:"enable_iis_worker_process"` //nolint:tagliatelle
ProcessInclude *regexp.Regexp `yaml:"include"`
ProcessExclude *regexp.Regexp `yaml:"exclude"`
EnableWorkerProcess bool `yaml:"iis"`
}
//nolint:gochecknoglobals

View File

@@ -36,8 +36,8 @@ import (
const Name = "scheduled_task"
type Config struct {
TaskExclude *regexp.Regexp `yaml:"task_exclude"`
TaskInclude *regexp.Regexp `yaml:"task_include"`
TaskExclude *regexp.Regexp `yaml:"exclude"`
TaskInclude *regexp.Regexp `yaml:"include"`
}
//nolint:gochecknoglobals

View File

@@ -38,8 +38,8 @@ import (
const Name = "service"
type Config struct {
ServiceInclude *regexp.Regexp `yaml:"service_include"`
ServiceExclude *regexp.Regexp `yaml:"service_exclude"`
ServiceInclude *regexp.Regexp `yaml:"include"`
ServiceExclude *regexp.Regexp `yaml:"exclude"`
}
//nolint:gochecknoglobals

View File

@@ -32,8 +32,8 @@ import (
const Name = "smtp"
type Config struct {
ServerInclude *regexp.Regexp `yaml:"server_include"`
ServerExclude *regexp.Regexp `yaml:"server_exclude"`
ServerInclude *regexp.Regexp `yaml:"server-include"`
ServerExclude *regexp.Regexp `yaml:"server-exclude"`
}
//nolint:gochecknoglobals

View File

@@ -36,7 +36,7 @@ import (
const Name = "tcp"
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -41,7 +41,7 @@ import (
const Name = "textfile"
type Config struct {
TextFileDirectories []string `yaml:"text_file_directories"`
TextFileDirectories []string `yaml:"directories"`
}
//nolint:gochecknoglobals

View File

@@ -43,7 +43,7 @@ const (
)
type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
CollectorsEnabled []string `yaml:"enabled"`
}
//nolint:gochecknoglobals

View File

@@ -19,13 +19,49 @@ package config
import (
"fmt"
"io"
"os"
"strings"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/pkg/collector"
"gopkg.in/yaml.v3"
)
// configFile represents the structure of the windows_exporter configuration file,
// including configuration from the collector and web packages.
type configFile struct {
Debug struct {
Enabled bool `yaml:"enabled"`
} `yaml:"debug"`
Collectors struct {
Enabled string `yaml:"enabled"`
} `yaml:"collectors"`
Collector collector.Config `yaml:"collector"`
Log struct {
Level string `yaml:"level"`
Format string `yaml:"format"`
File string `yaml:"file"`
} `yaml:"log"`
Process struct {
Priority string `yaml:"priority"`
MemoryLimit string `yaml:"memory-limit"`
} `yaml:"process"`
Scrape struct {
TimeoutMargin string `yaml:"timeout-margin"`
} `yaml:"scrape"`
Telemetry struct {
Path string `yaml:"path"`
} `yaml:"telemetry"`
Web struct {
DisableExporterMetrics bool `yaml:"disable-exporter-metrics"`
ListenAddresses any `yaml:"listen-address"`
Config struct {
File string `yaml:"file"`
} `yaml:"config"`
} `yaml:"web"`
}
type getFlagger interface {
GetFlag(name string) *kingpin.FlagClause
}
@@ -80,24 +116,37 @@ func ParseConfigFile(args []string) string {
}
// NewConfigFileResolver returns a Resolver structure.
func NewConfigFileResolver(file string) (*Resolver, error) {
func NewConfigFileResolver(filePath string) (*Resolver, error) {
flags := map[string]string{}
var (
err error
fileBytes []byte
)
fileBytes, err = readFromFile(file)
file, err := os.Open(filePath)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to open configuration file: %w", err)
}
defer func() {
_ = file.Close()
}()
var configFileStructure configFile
decoder := yaml.NewDecoder(file)
decoder.KnownFields(true)
if err = decoder.Decode(&configFileStructure); err != nil {
return nil, fmt.Errorf("configuration file validation error: %w", err)
}
_, err = file.Seek(0, io.SeekStart)
if err != nil {
return nil, fmt.Errorf("failed to rewind file: %w", err)
}
var rawValues map[string]interface{}
err = yaml.Unmarshal(fileBytes, &rawValues)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal configuration file: %w", err)
decoder = yaml.NewDecoder(file)
if err = decoder.Decode(&rawValues); err != nil {
return nil, fmt.Errorf("failed to parse configuration file: %w", err)
}
// Flatten nested YAML values
@@ -111,23 +160,9 @@ func NewConfigFileResolver(file string) (*Resolver, error) {
return &Resolver{flags: flags}, nil
}
func readFromFile(file string) ([]byte, error) {
if _, err := os.Stat(file); err != nil {
return nil, fmt.Errorf("failed to read configuration file: %w", err)
}
fileBytes, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("failed to read configuration file: %w", err)
}
return fileBytes, nil
}
func (c *Resolver) setDefault(v getFlagger) {
for name, value := range c.flags {
f := v.GetFlag(name)
if f != nil {
if f := v.GetFlag(name); f != nil {
f.Default(value)
}
}

View File

@@ -79,26 +79,26 @@ type Config struct {
Cs cs.Config `yaml:"cs"`
DFSR dfsr.Config `yaml:"dfsr"`
Dhcp dhcp.Config `yaml:"dhcp"`
DiskDrive diskdrive.Config `yaml:"disk_drive"`
DiskDrive diskdrive.Config `yaml:"diskdrive"`
DNS dns.Config `yaml:"dns"`
Exchange exchange.Config `yaml:"exchange"`
Filetime filetime.Config `yaml:"filetime"`
Fsrmquota fsrmquota.Config `yaml:"fsrmquota"`
HyperV hyperv.Config `yaml:"hyper_v"`
HyperV hyperv.Config `yaml:"hyperv"`
IIS iis.Config `yaml:"iis"`
License license.Config `yaml:"license"`
LogicalDisk logical_disk.Config `yaml:"logical_disk"`
Logon logon.Config `yaml:"logon"`
Memory memory.Config `yaml:"memory"`
MSCluster mscluster.Config `yaml:"ms_cluster"`
MSCluster mscluster.Config `yaml:"mscluster"`
Msmq msmq.Config `yaml:"msmq"`
Mssql mssql.Config `yaml:"mssql"`
Net net.Config `yaml:"net"`
NetFramework netframework.Config `yaml:"net_framework"`
NetFramework netframework.Config `yaml:"netframework"`
Nps nps.Config `yaml:"nps"`
OS os.Config `yaml:"os"`
Paging pagefile.Config `yaml:"paging"`
PerformanceCounter performancecounter.Config `yaml:"performance_counter"`
PerformanceCounter performancecounter.Config `yaml:"performancecounter"`
PhysicalDisk physical_disk.Config `yaml:"physical_disk"`
Printer printer.Config `yaml:"printer"`
Process process.Config `yaml:"process"`
@@ -112,7 +112,7 @@ type Config struct {
TCP tcp.Config `yaml:"tcp"`
TerminalServices terminal_services.Config `yaml:"terminal_services"`
Textfile textfile.Config `yaml:"textfile"`
ThermalZone thermalzone.Config `yaml:"thermal_zone"`
ThermalZone thermalzone.Config `yaml:"thermalzone"`
Time time.Config `yaml:"time"`
UDP udp.Config `yaml:"udp"`
Update update.Config `yaml:"update"`