Permalink
Browse files

cmd/bosun: define rule vars in sysconfig

  • Loading branch information...
kylebrandt committed Apr 4, 2017
1 parent a76718c commit c699b451e282b903d0a164a41e54c4b15a4253e9
View
@@ -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
@@ -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
}
@@ -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)
}
@@ -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
@@ -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,
@@ -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 {
@@ -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 {
@@ -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)
}
@@ -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
View
@@ -39,6 +39,8 @@ type SystemConf struct {
SMTPConf SMTPConf
RuleVars map[string]string
OpenTSDBConf OpenTSDBConf
GraphiteConf GraphiteConf
InfluxConf InfluxConf
@@ -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
View
@@ -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)
}
@@ -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
}
@@ -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
}
@@ -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"
@@ -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
}
@@ -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}}
}
@@ -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
}
@@ -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
}
@@ -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}}
}
@@ -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)
}
@@ -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
}
@@ -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)
View
@@ -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
}
View
@@ -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())
}
@@ -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"}}
}
@@ -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").
@@ -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.

0 comments on commit c699b45

Please sign in to comment.