...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package cli
15
16 import (
17 "bytes"
18 "context"
19 "fmt"
20
21 "github.com/xlab/treeprint"
22 "gopkg.in/alecthomas/kingpin.v2"
23
24 "github.com/prometheus/alertmanager/api/v2/models"
25 "github.com/prometheus/alertmanager/dispatch"
26 )
27
28 type routingShow struct {
29 configFile string
30 labels []string
31 expectedReceivers string
32 debugTree bool
33 }
34
35 const (
36 routingHelp = `Prints alert routing tree
37
38 Will print whole routing tree in form of ASCII tree view.
39
40 Routing is loaded from a local configuration file or a running Alertmanager configuration.
41 Specifying --config.file takes precedence over --alertmanager.url.
42
43 Example:
44
45 ./amtool config routes [show] --config.file=doc/examples/simple.yml
46
47 `
48 branchSlugSeparator = " "
49 )
50
51 func configureRoutingCmd(app *kingpin.CmdClause) {
52 var (
53 c = &routingShow{}
54 routingCmd = app.Command("routes", routingHelp)
55 routingShowCmd = routingCmd.Command("show", routingHelp).Default()
56 configFlag = routingCmd.Flag("config.file", "Config file to be tested.")
57 )
58 configFlag.ExistingFileVar(&c.configFile)
59 routingShowCmd.Action(execWithTimeout(c.routingShowAction))
60 configureRoutingTestCmd(routingCmd, c)
61 }
62
63 func (c *routingShow) routingShowAction(ctx context.Context, _ *kingpin.ParseContext) error {
64
65 cfg, err := loadAlertmanagerConfig(ctx, alertmanagerURL, c.configFile)
66 if err != nil {
67 kingpin.Fatalf("%s", err)
68 return err
69 }
70 route := dispatch.NewRoute(cfg.Route, nil)
71 tree := treeprint.New()
72 convertRouteToTree(route, tree)
73 fmt.Println("Routing tree:")
74 fmt.Println(tree.String())
75 return nil
76 }
77
78 func getRouteTreeSlug(route *dispatch.Route, showContinue, showReceiver bool) string {
79 var branchSlug bytes.Buffer
80 if route.Matchers.Len() == 0 {
81 branchSlug.WriteString("default-route")
82 } else {
83 branchSlug.WriteString(route.Matchers.String())
84 }
85 if route.Continue && showContinue {
86 branchSlug.WriteString(branchSlugSeparator)
87 branchSlug.WriteString("continue: true")
88 }
89 if showReceiver {
90 branchSlug.WriteString(branchSlugSeparator)
91 branchSlug.WriteString("receiver: ")
92 branchSlug.WriteString(route.RouteOpts.Receiver)
93 }
94 return branchSlug.String()
95 }
96
97 func convertRouteToTree(route *dispatch.Route, tree treeprint.Tree) {
98 branch := tree.AddBranch(getRouteTreeSlug(route, true, true))
99 for _, r := range route.Routes {
100 convertRouteToTree(r, branch)
101 }
102 }
103
104 func getMatchingTree(route *dispatch.Route, tree treeprint.Tree, lset models.LabelSet) {
105 final := true
106 branch := tree.AddBranch(getRouteTreeSlug(route, false, false))
107 for _, r := range route.Routes {
108 if r.Matchers.Matches(convertClientToCommonLabelSet(lset)) {
109 getMatchingTree(r, branch, lset)
110 final = false
111 if !r.Continue {
112 break
113 }
114 }
115 }
116 if final {
117 branch.SetValue(getRouteTreeSlug(route, false, true))
118 }
119 }
120
View as plain text