Load rule files from entire directories

This commit is contained in:
Fabian Reinartz 2015-05-28 07:36:21 +02:00
parent ed6572fc0c
commit c44ac7bc26
5 changed files with 26 additions and 1 deletions

View file

@ -18,6 +18,7 @@ import (
var ( var (
patJobName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`) patJobName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
patFileSDName = regexp.MustCompile(`^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$`) patFileSDName = regexp.MustCompile(`^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$`)
patRulePath = regexp.MustCompile(`^[^*]*(\*[^/]*)?$`)
) )
// Load parses the YAML input s into a Config. // Load parses the YAML input s into a Config.
@ -112,6 +113,11 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&c.DefaultedConfig); err != nil { if err := unmarshal(&c.DefaultedConfig); err != nil {
return err return err
} }
for _, rf := range c.RuleFiles {
if !patRulePath.MatchString(rf) {
return fmt.Errorf("invalid rule file path %q", rf)
}
}
// Do global overrides and validate unique names. // Do global overrides and validate unique names.
jobNames := map[string]struct{}{} jobNames := map[string]struct{}{}
for _, scfg := range c.ScrapeConfigs { for _, scfg := range c.ScrapeConfigs {

View file

@ -27,6 +27,7 @@ var expectedConf = &Config{DefaultedConfig{
RuleFiles: []string{ RuleFiles: []string{
"first.rules", "first.rules",
"second.rules", "second.rules",
"my/*.rules",
}, },
ScrapeConfigs: []*ScrapeConfig{ ScrapeConfigs: []*ScrapeConfig{
@ -151,6 +152,9 @@ var expectedErrors = []struct {
}, { }, {
filename: "regex.bad.yml", filename: "regex.bad.yml",
errMsg: "error parsing regexp", errMsg: "error parsing regexp",
}, {
filename: "rules.bad.yml",
errMsg: "invalid rule file path",
}, },
} }
@ -159,6 +163,7 @@ func TestBadConfigs(t *testing.T) {
_, err := LoadFromFile("testdata/" + ee.filename) _, err := LoadFromFile("testdata/" + ee.filename)
if err == nil { if err == nil {
t.Errorf("Expected error parsing %s but got none", ee.filename) t.Errorf("Expected error parsing %s but got none", ee.filename)
continue
} }
if !strings.Contains(err.Error(), ee.errMsg) { if !strings.Contains(err.Error(), ee.errMsg) {
t.Errorf("Expected error for %s to contain %q but got: %s", ee.filename, ee.errMsg, err) t.Errorf("Expected error for %s to contain %q but got: %s", ee.filename, ee.errMsg, err)

View file

@ -11,6 +11,7 @@ global:
rule_files: rule_files:
- "first.rules" - "first.rules"
- "second.rules" - "second.rules"
- "my/*.rules"
scrape_configs: scrape_configs:
- job_name: prometheus - job_name: prometheus

3
config/testdata/rules.bad.yml vendored Normal file
View file

@ -0,0 +1,3 @@
rule_files:
- 'my_rule' # fine
- 'my/*/rule' # bad

View file

@ -16,6 +16,7 @@ package rules
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -281,7 +282,16 @@ func (m *Manager) ApplyConfig(conf *config.Config) {
copy(rulesSnapshot, m.rules) copy(rulesSnapshot, m.rules)
m.rules = m.rules[:0] m.rules = m.rules[:0]
if err := m.loadRuleFiles(conf.RuleFiles...); err != nil { var files []string
for _, pat := range conf.RuleFiles {
fs, err := filepath.Glob(pat)
if err != nil {
// The only error can be a bad pattern.
log.Errorf("Error retrieving rule files for %s: %s", pat, err)
}
files = append(files, fs...)
}
if err := m.loadRuleFiles(files...); err != nil {
// If loading the new rules failed, restore the old rule set. // If loading the new rules failed, restore the old rule set.
m.rules = rulesSnapshot m.rules = rulesSnapshot
log.Errorf("Error loading rules, previous rule set restored: %s", err) log.Errorf("Error loading rules, previous rule set restored: %s", err)