Skip to content

Commit

Permalink
cmd/bosun: define rule vars in sysconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebrandt committed Apr 4, 2017
1 parent a76718c commit c699b45
Show file tree
Hide file tree
Showing 13 changed files with 60 additions and 23 deletions.
2 changes: 2 additions & 0 deletions cmd/bosun/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type SystemConfProvider interface {
GetTLSCertFile() string
GetTLSKeyFile() string

GetRuleVars() map[string]string

GetSMTPHost() string
GetSMTPUsername() string // SMTP username
GetSMTPPassword() string // SMTP password
Expand Down
4 changes: 2 additions & 2 deletions cmd/bosun/conf/rule/modify.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// will not be saved. If the savehook fails to run or returns an error thaen the orginal config
// will be restored and the reload will not take place.
func (c *Conf) SaveRawText(rawConfig, diff, user, message string, args ...string) error {
newConf, err := NewConf(c.Name, c.backends, rawConfig)
newConf, err := NewConf(c.Name, c.backends, c.sysVars, rawConfig)
if err != nil {
return err
}
Expand Down Expand Up @@ -101,7 +101,7 @@ func (c *Conf) BulkEdit(edits conf.BulkEditRequest) error {
} else {
rawConf = writeSection(l, newConf.RawText, edit.Text)
}
newConf, err = NewConf(c.Name, c.backends, rawConf)
newConf, err = NewConf(c.Name, c.backends, c.sysVars, rawConf)
if err != nil {
return fmt.Errorf("could not create new conf: failed on step %v:%v : %v", edit.Type, edit.Name, err)
}
Expand Down
11 changes: 8 additions & 3 deletions cmd/bosun/conf/rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type Conf struct {
reload func() error
backends conf.EnabledBackends

sysVars map[string]string

tree *parse.Tree
node parse.Node
unknownTemplate string
Expand Down Expand Up @@ -125,19 +127,19 @@ func (c *Conf) parseNotifications(v string) (map[string]*conf.Notification, erro
return ns, nil
}

func ParseFile(fname string, backends conf.EnabledBackends) (*Conf, error) {
func ParseFile(fname string, backends conf.EnabledBackends, sysVars map[string]string) (*Conf, error) {
f, err := ioutil.ReadFile(fname)
if err != nil {
return nil, err
}
return NewConf(fname, backends, string(f))
return NewConf(fname, backends, sysVars, string(f))
}

func (c *Conf) SaveConf(newConf *Conf) error {
return ioutil.WriteFile(c.Name, []byte(newConf.RawText), os.FileMode(int(0640)))
}

func NewConf(name string, backends conf.EnabledBackends, text string) (c *Conf, err error) {
func NewConf(name string, backends conf.EnabledBackends, sysVars map[string]string, text string) (c *Conf, err error) {
defer errRecover(&err)
c = &Conf{
Name: name,
Expand All @@ -153,6 +155,7 @@ func NewConf(name string, backends conf.EnabledBackends, text string) (c *Conf,
writeLock: make(chan bool, 1),
deferredSections: make(map[string][]deferredSection),
backends: backends,
sysVars: sysVars,
}
c.tree, err = parse.Parse(name, text)
if err != nil {
Expand Down Expand Up @@ -776,6 +779,8 @@ func (c *Conf) Expand(v string, vars map[string]string, ignoreBadExpand bool) st
n = _n
} else if strings.HasPrefix(s, "$env.") {
n = os.Getenv(s[5:])
} else if strings.HasPrefix(s, "$sys.") {
n = c.sysVars[s[5:]]
} else if ignoreBadExpand {
return s
} else {
Expand Down
4 changes: 2 additions & 2 deletions cmd/bosun/conf/rule/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestPrint(t *testing.T) {
if err := os.Setenv("env", "1"); err != nil {
t.Fatal(err)
}
c, err := NewConf(fname, conf.EnabledBackends{OpenTSDB: true}, string(b))
c, err := NewConf(fname, conf.EnabledBackends{OpenTSDB: true}, nil, string(b))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestInvalid(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, err = NewConf(fname, conf.EnabledBackends{OpenTSDB: true}, string(b))
_, err = NewConf(fname, conf.EnabledBackends{OpenTSDB: true}, nil, string(b))
if err == nil {
t.Error("expected error in", path)
continue
Expand Down
8 changes: 8 additions & 0 deletions cmd/bosun/conf/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type SystemConf struct {

SMTPConf SMTPConf

RuleVars map[string]string

OpenTSDBConf OpenTSDBConf
GraphiteConf GraphiteConf
InfluxConf InfluxConf
Expand Down Expand Up @@ -333,6 +335,12 @@ func (sc *SystemConf) GetAuthConf() *AuthConf {
return sc.AuthConf
}

// GetRuleVars user defined variables that will be available to the rule configuration
// under "$sys.". This is so values with secrets can be defined in the system configuration
func (sc *SystemConf) GetRuleVars() map[string]string {
return sc.RuleVars
}

// GetTimeAndDate returns the http://www.timeanddate.com/ that should be available to the UI
// so it can show links to translate UTC times to various timezones. This feature is only
// for creating UI Links as Bosun is expected to be running on a machine that is set to UTC
Expand Down
4 changes: 2 additions & 2 deletions cmd/bosun/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func main() {
if err != nil {
slog.Fatal(err)
}
ruleConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), systemConf.EnabledBackends())
ruleConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), systemConf.EnabledBackends(), systemConf.GetRuleVars())
if err != nil {
slog.Fatalf("couldn't read rules: %v", err)
}
Expand Down Expand Up @@ -219,7 +219,7 @@ func main() {
defer func() {
<-reloading
}()
newConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), sysProvider.EnabledBackends())
newConf, err := rule.ParseFile(sysProvider.GetRuleFilePath(), sysProvider.EnabledBackends(), sysProvider.GetRuleVars())
if err != nil {
return err
}
Expand Down
14 changes: 7 additions & 7 deletions cmd/bosun/sched/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

func TestCheckFlapping(t *testing.T) {
defer setup()()
c, err := rule.NewConf("", conf.EnabledBackends{}, `
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, `
template t {
subject = 1
}
Expand Down Expand Up @@ -106,7 +106,7 @@ func TestCheckSilence(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := rule.NewConf("", conf.EnabledBackends{}, fmt.Sprintf(`
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, fmt.Sprintf(`
template t {
subject = "test"
body = "test"
Expand Down Expand Up @@ -143,7 +143,7 @@ func TestCheckSilence(t *testing.T) {

func TestIncidentIds(t *testing.T) {
defer setup()()
c, err := rule.NewConf("", conf.EnabledBackends{}, `
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, `
alert a {
crit = 1
}
Expand Down Expand Up @@ -201,7 +201,7 @@ func TestCheckNotify(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := rule.NewConf("", conf.EnabledBackends{}, fmt.Sprintf(`
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, fmt.Sprintf(`
template t {
subject = {{.Last.Status}}
}
Expand Down Expand Up @@ -245,7 +245,7 @@ func TestCheckNotifyUnknown(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := rule.NewConf("", conf.EnabledBackends{}, fmt.Sprintf(`
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, fmt.Sprintf(`
template t {
subject = {{.Name}}: {{.Group | len}} unknown alerts
}
Expand Down Expand Up @@ -308,7 +308,7 @@ func TestCheckNotifyUnknownDefault(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := rule.NewConf("", conf.EnabledBackends{}, fmt.Sprintf(`
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, fmt.Sprintf(`
template t {
subject = template
}
Expand Down Expand Up @@ -369,7 +369,7 @@ func TestCheckNotifyLog(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := rule.NewConf("", conf.EnabledBackends{}, fmt.Sprintf(`
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, fmt.Sprintf(`
template t {
subject = {{.Alert.Name}}
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/bosun/sched/notification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func TestActionNotificationTemplates(t *testing.T) {
c, err := rule.NewConf("", conf.EnabledBackends{}, ``)
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, ``)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -53,7 +53,7 @@ func TestActionNotificationTemplates(t *testing.T) {

func TestActionNotificationGrouping(t *testing.T) {
defer setup()()
c, err := rule.NewConf("", conf.EnabledBackends{}, `
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, `
template t{
subject = 2
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/bosun/sched/sched_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func testSched(t *testing.T, st *schedTest) (s *Schedule) {
t.Fatal(err)
}
//confs := "tsdbHost = " + u.Host + "\n" + st.conf
c, err := rule.NewConf("testconf", conf.EnabledBackends{OpenTSDB: true}, st.conf)
c, err := rule.NewConf("testconf", conf.EnabledBackends{OpenTSDB: true}, nil, st.conf)
if err != nil {
t.Error(err)
t.Logf("conf:\n%s", st.conf)
Expand Down
2 changes: 1 addition & 1 deletion cmd/bosun/web/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ func buildConfig(r *http.Request) (c conf.RuleConfProvider, a *conf.Alert, hash
if err != nil {
return nil, nil, "", err
}
c, err = rule.NewConf("Test Config", schedule.SystemConf.EnabledBackends(), string(config))
c, err = rule.NewConf("Test Config", schedule.SystemConf.EnabledBackends(), schedule.SystemConf.GetRuleVars(), string(config))
if err != nil {
return nil, nil, "", err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/bosun/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ func ConfigTest(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (i
if len(b) == 0 {
return nil, fmt.Errorf("empty config")
}
_, err = rule.NewConf("test", schedule.SystemConf.EnabledBackends(), string(b))
_, err = rule.NewConf("test", schedule.SystemConf.EnabledBackends(), schedule.SystemConf.GetRuleVars(), string(b))
if err != nil {
fmt.Fprintf(w, err.Error())
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/bosun/web/web_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestErrorTemplate(t *testing.T) {
c, err := rule.NewConf("", conf.EnabledBackends{}, `
c, err := rule.NewConf("", conf.EnabledBackends{}, nil, `
template t {
body = {{.Eval "invalid"}}
}
Expand Down
24 changes: 23 additions & 1 deletion docs/system_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Example:
`CheckFrequency = "1m"`

### DefaultRunEvery
By default, alert checks are run at every [`CheckFrequency`](/system_configuration#checkevery) multiplied by the `DefaultRunEvery` value. This can be overridden in an alert definition with the [`runEvery` keyword](http://localhost:4000/definitions#runevery). This defaults to 1.
By default, alert checks are run at every [`CheckFrequency`](/system_configuration#checkevery) multiplied by the `DefaultRunEvery` value. This can be overridden in an alert definition with the [`runEvery` keyword](/definitions#runevery). This defaults to 1.

So for example if you have a `CheckFrequency` of "1m" and a `DefaultRunEvery` of 5, alerts by default will run every 5 minutes. But you could have some run as frequent as every "1m", and others that run less often (any multiple of "1m").

Expand Down Expand Up @@ -150,6 +150,28 @@ But not sure I trust that.
## Configuration Sections
All your key value pairs must be defined before any sections are defined. Sections are used for things that have multiple values to configure them. In particular the various time series database providers.

### RuleVars
Rule vars lets you define variables that will then be turned into [global variables](/definitions#global-variables) available to definitions under `$sys.`. This is designed for when you have some secrets you don't want exposed in the definitions file. The values of these variables *can* still be accessed from Bosun's rule editor and expression UI, so this only helps hide them so you don't accidentally include them in screenshots or when copying and pasting your config.

Example:

```
[RuleVars]
CHAT = "https://chat.example.com/1?key=mySecretKey"
foo = "baz"
```

The above could then be used in the rule configuration like:

```
notification chat {
post = ${sys.CHAT}
runOnActions = false
}
```

They can also be accessed in templates with the [`V()` function](/definitions#vstring-string)

### DBConf
`DBConf` defines what internal storage Bosun should use. There are currently two choices, a built-in redis like server called ledis or redis. Redis is recommended for production setups.

Expand Down

0 comments on commit c699b45

Please sign in to comment.