From cea1e99f78c739fe2261406313bfc673a5b77ddb Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Wed, 14 Jun 2017 11:13:00 +0530 Subject: [PATCH] Add update-rules command to promtool Signed-off-by: Goutham Veeramachaneni --- cmd/promtool/main.go | 88 ++++++++++++++++++++++++++++++++++++++++++ pkg/rulefmt/rulefmt.go | 12 +++--- rules/manager.go | 3 +- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/cmd/promtool/main.go b/cmd/promtool/main.go index 431d38135..cf2debf8f 100644 --- a/cmd/promtool/main.go +++ b/cmd/promtool/main.go @@ -20,8 +20,12 @@ import ( "path/filepath" "strings" + yaml "github.com/ghodss/yaml" + + "github.com/prometheus/common/model" "github.com/prometheus/common/version" "github.com/prometheus/prometheus/config" + "github.com/prometheus/prometheus/pkg/rulefmt" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/util/cli" "github.com/prometheus/prometheus/util/promlint" @@ -183,6 +187,85 @@ func checkRules(t cli.Term, filename string) (int, error) { return len(rules), nil } +// UpdateRulesCmd updates the rule files. +func UpdateRulesCmd(t cli.Term, args ...string) int { + if len(args) == 0 { + t.Infof("usage: promtool update-rules ") + return 2 + } + failed := false + + for _, arg := range args { + if err := updateRules(t, arg); err != nil { + t.Errorf(" FAILED: %s", err) + failed = true + } + } + + if failed { + return 1 + } + return 0 +} + +func updateRules(t cli.Term, filename string) error { + t.Infof("Updating %s", filename) + + if stat, err := os.Stat(filename); err != nil { + return fmt.Errorf("cannot get file info") + } else if stat.IsDir() { + return fmt.Errorf("is a directory") + } + + content, err := ioutil.ReadFile(filename) + if err != nil { + return err + } + + rules, err := promql.ParseStmts(string(content)) + if err != nil { + return err + } + + yamlRG := &rulefmt.RuleGroups{ + Version: 1, + Groups: []rulefmt.RuleGroup{{ + Name: filename, + }}, + } + + yamlRules := make([]rulefmt.Rule, 0, len(rules)) + + for _, rule := range rules { + switch r := rule.(type) { + case *promql.AlertStmt: + yamlRules = append(yamlRules, rulefmt.Rule{ + Alert: r.Name, + Expr: r.Expr.String(), + For: model.Duration(r.Duration).String(), + Labels: r.Labels.Map(), + Annotations: r.Annotations.Map(), + }) + case *promql.RecordStmt: + yamlRules = append(yamlRules, rulefmt.Rule{ + Record: r.Name, + Expr: r.Expr.String(), + Labels: r.Labels.Map(), + }) + default: + panic("unknown statement type") + } + } + + yamlRG.Groups[0].Rules = yamlRules + y, err := yaml.Marshal(yamlRG) + if err != nil { + return err + } + + return ioutil.WriteFile(filename+".yaml", y, 0777) +} + var checkMetricsUsage = strings.TrimSpace(` usage: promtool check-metrics @@ -243,6 +326,11 @@ func main() { Run: CheckMetricsCmd, }) + app.Register("update-rules", &cli.Command{ + Desc: "update the rules to the new YAML format", + Run: UpdateRulesCmd, + }) + app.Register("version", &cli.Command{ Desc: "print the version of this binary", Run: VersionCmd, diff --git a/pkg/rulefmt/rulefmt.go b/pkg/rulefmt/rulefmt.go index ee0e6df6c..3453ce5d6 100644 --- a/pkg/rulefmt/rulefmt.go +++ b/pkg/rulefmt/rulefmt.go @@ -47,18 +47,18 @@ func (g *RuleGroups) Validate() (errs []error) { // RuleGroup is a list of sequentially evaluated recording and alerting rules. type RuleGroup struct { Name string `json:"name"` - Interval string `json:"interval"` + Interval string `json:"interval,omitempty"` Rules []Rule `json:"rules"` } // Rule describes an alerting or recording rule. type Rule struct { - Record string `json:"record"` - Alert string `json:"alert"` + Record string `json:"record,omitempty"` + Alert string `json:"alert,omitempty"` Expr string `json:"expr"` - For string `json:"for"` - Labels map[string]string `json:"labels"` - Annotations map[string]string `json:"annotations"` + For string `json:"for,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` } // Validate the rule and return a list of encountered errors. diff --git a/rules/manager.go b/rules/manager.go index 74322877c..fcfcba606 100644 --- a/rules/manager.go +++ b/rules/manager.go @@ -390,6 +390,7 @@ type Manager struct { block chan struct{} } +// Appendable returns an Appender. type Appendable interface { Appender() (storage.Appender, error) } @@ -517,7 +518,7 @@ func (m *Manager) loadGroups(interval time.Duration, filenames ...string) (map[s itv = time.Duration(dur) } - rules := make([]Rule, len(rg.Rules), 0) + rules := make([]Rule, 0, len(rg.Rules)) for _, r := range rg.Rules { expr, err := promql.ParseExpr(r.Expr) if err != nil {