github.com/netdata/go.d.plugin@v0.58.1/agent/discovery/sd/pipeline/classify.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package pipeline 4 5 import ( 6 "bytes" 7 "strings" 8 "text/template" 9 10 "github.com/netdata/go.d.plugin/agent/discovery/sd/model" 11 "github.com/netdata/go.d.plugin/logger" 12 ) 13 14 func newTargetClassificator(cfg []ClassifyRuleConfig) (*targetClassificator, error) { 15 rules, err := newClassifyRules(cfg) 16 if err != nil { 17 return nil, err 18 } 19 20 c := &targetClassificator{ 21 rules: rules, 22 buf: bytes.Buffer{}, 23 } 24 25 return c, nil 26 } 27 28 type ( 29 targetClassificator struct { 30 *logger.Logger 31 rules []*classifyRule 32 buf bytes.Buffer 33 } 34 35 classifyRule struct { 36 name string 37 sr selector 38 tags model.Tags 39 match []*classifyRuleMatch 40 } 41 classifyRuleMatch struct { 42 tags model.Tags 43 expr *template.Template 44 } 45 ) 46 47 func (c *targetClassificator) classify(tgt model.Target) model.Tags { 48 var tags model.Tags 49 50 for i, rule := range c.rules { 51 if !rule.sr.matches(tgt.Tags()) { 52 continue 53 } 54 55 for j, match := range rule.match { 56 c.buf.Reset() 57 58 if err := match.expr.Execute(&c.buf, tgt); err != nil { 59 c.Warningf("failed to execute classify rule[%d]->match[%d]->expr on target '%s'", i+1, j+1, tgt.TUID()) 60 continue 61 } 62 if strings.TrimSpace(c.buf.String()) != "true" { 63 continue 64 } 65 66 if tags == nil { 67 tags = model.NewTags() 68 } 69 70 tags.Merge(rule.tags) 71 tags.Merge(match.tags) 72 } 73 } 74 75 return tags 76 } 77 78 func newClassifyRules(cfg []ClassifyRuleConfig) ([]*classifyRule, error) { 79 var rules []*classifyRule 80 81 fmap := newFuncMap() 82 83 for _, ruleCfg := range cfg { 84 rule := classifyRule{name: ruleCfg.Name} 85 86 sr, err := parseSelector(ruleCfg.Selector) 87 if err != nil { 88 return nil, err 89 } 90 rule.sr = sr 91 92 tags, err := model.ParseTags(ruleCfg.Tags) 93 if err != nil { 94 return nil, err 95 } 96 rule.tags = tags 97 98 for _, matchCfg := range ruleCfg.Match { 99 var match classifyRuleMatch 100 101 tags, err := model.ParseTags(matchCfg.Tags) 102 if err != nil { 103 return nil, err 104 } 105 match.tags = tags 106 107 tmpl, err := parseTemplate(matchCfg.Expr, fmap) 108 if err != nil { 109 return nil, err 110 } 111 match.expr = tmpl 112 113 rule.match = append(rule.match, &match) 114 } 115 116 rules = append(rules, &rule) 117 } 118 119 return rules, nil 120 } 121 122 func parseTemplate(s string, fmap template.FuncMap) (*template.Template, error) { 123 return template.New("root"). 124 Option("missingkey=error"). 125 Funcs(fmap). 126 Parse(s) 127 }