github.com/netdata/go.d.plugin@v0.58.1/modules/vsphere/match/match.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package match 4 5 import ( 6 "fmt" 7 "strings" 8 9 rs "github.com/netdata/go.d.plugin/modules/vsphere/resources" 10 "github.com/netdata/go.d.plugin/pkg/matcher" 11 ) 12 13 type HostMatcher interface { 14 Match(*rs.Host) bool 15 } 16 17 type VMMatcher interface { 18 Match(*rs.VM) bool 19 } 20 21 type ( 22 hostDCMatcher struct{ m matcher.Matcher } 23 hostClusterMatcher struct{ m matcher.Matcher } 24 hostHostMatcher struct{ m matcher.Matcher } 25 vmDCMatcher struct{ m matcher.Matcher } 26 vmClusterMatcher struct{ m matcher.Matcher } 27 vmHostMatcher struct{ m matcher.Matcher } 28 vmVMMatcher struct{ m matcher.Matcher } 29 orHostMatcher struct{ lhs, rhs HostMatcher } 30 orVMMatcher struct{ lhs, rhs VMMatcher } 31 andHostMatcher struct{ lhs, rhs HostMatcher } 32 andVMMatcher struct{ lhs, rhs VMMatcher } 33 ) 34 35 func (m hostDCMatcher) Match(host *rs.Host) bool { return m.m.MatchString(host.Hier.DC.Name) } 36 func (m hostClusterMatcher) Match(host *rs.Host) bool { return m.m.MatchString(host.Hier.Cluster.Name) } 37 func (m hostHostMatcher) Match(host *rs.Host) bool { return m.m.MatchString(host.Name) } 38 func (m vmDCMatcher) Match(vm *rs.VM) bool { return m.m.MatchString(vm.Hier.DC.Name) } 39 func (m vmClusterMatcher) Match(vm *rs.VM) bool { return m.m.MatchString(vm.Hier.Cluster.Name) } 40 func (m vmHostMatcher) Match(vm *rs.VM) bool { return m.m.MatchString(vm.Hier.Host.Name) } 41 func (m vmVMMatcher) Match(vm *rs.VM) bool { return m.m.MatchString(vm.Name) } 42 func (m orHostMatcher) Match(host *rs.Host) bool { return m.lhs.Match(host) || m.rhs.Match(host) } 43 func (m orVMMatcher) Match(vm *rs.VM) bool { return m.lhs.Match(vm) || m.rhs.Match(vm) } 44 func (m andHostMatcher) Match(host *rs.Host) bool { return m.lhs.Match(host) && m.rhs.Match(host) } 45 func (m andVMMatcher) Match(vm *rs.VM) bool { return m.lhs.Match(vm) && m.rhs.Match(vm) } 46 47 func newAndHostMatcher(lhs, rhs HostMatcher, others ...HostMatcher) andHostMatcher { 48 m := andHostMatcher{lhs: lhs, rhs: rhs} 49 switch len(others) { 50 case 0: 51 return m 52 default: 53 return newAndHostMatcher(m, others[0], others[1:]...) 54 } 55 } 56 57 func newAndVMMatcher(lhs, rhs VMMatcher, others ...VMMatcher) andVMMatcher { 58 m := andVMMatcher{lhs: lhs, rhs: rhs} 59 switch len(others) { 60 case 0: 61 return m 62 default: 63 return newAndVMMatcher(m, others[0], others[1:]...) 64 } 65 } 66 67 func newOrHostMatcher(lhs, rhs HostMatcher, others ...HostMatcher) orHostMatcher { 68 m := orHostMatcher{lhs: lhs, rhs: rhs} 69 switch len(others) { 70 case 0: 71 return m 72 default: 73 return newOrHostMatcher(m, others[0], others[1:]...) 74 } 75 } 76 77 func newOrVMMatcher(lhs, rhs VMMatcher, others ...VMMatcher) orVMMatcher { 78 m := orVMMatcher{lhs: lhs, rhs: rhs} 79 switch len(others) { 80 case 0: 81 return m 82 default: 83 return newOrVMMatcher(m, others[0], others[1:]...) 84 } 85 } 86 87 type ( 88 VMIncludes []string 89 HostIncludes []string 90 ) 91 92 func (vi VMIncludes) Parse() (VMMatcher, error) { 93 var ms []VMMatcher 94 for _, v := range vi { 95 m, err := parseVMInclude(v) 96 if err != nil { 97 return nil, err 98 } 99 if m == nil { 100 continue 101 } 102 ms = append(ms, m) 103 } 104 105 switch len(ms) { 106 case 0: 107 return nil, nil 108 case 1: 109 return ms[0], nil 110 default: 111 return newOrVMMatcher(ms[0], ms[1], ms[2:]...), nil 112 } 113 } 114 115 func (hi HostIncludes) Parse() (HostMatcher, error) { 116 var ms []HostMatcher 117 for _, v := range hi { 118 m, err := parseHostInclude(v) 119 if err != nil { 120 return nil, err 121 } 122 if m == nil { 123 continue 124 } 125 ms = append(ms, m) 126 } 127 128 switch len(ms) { 129 case 0: 130 return nil, nil 131 case 1: 132 return ms[0], nil 133 default: 134 return newOrHostMatcher(ms[0], ms[1], ms[2:]...), nil 135 } 136 } 137 138 const ( 139 datacenterIdx = iota 140 clusterIdx 141 hostIdx 142 vmIdx 143 ) 144 145 func cleanInclude(include string) string { 146 return strings.Trim(include, "/") 147 } 148 149 func parseHostInclude(include string) (HostMatcher, error) { 150 if !isIncludeFormatValid(include) { 151 return nil, fmt.Errorf("bad include format: %s", include) 152 } 153 154 include = cleanInclude(include) 155 parts := strings.Split(include, "/") // /dc/clusterIdx/hostIdx 156 var ms []HostMatcher 157 158 for i, v := range parts { 159 m, err := parseSubInclude(v) 160 if err != nil { 161 return nil, err 162 } 163 switch i { 164 case datacenterIdx: 165 ms = append(ms, hostDCMatcher{m}) 166 case clusterIdx: 167 ms = append(ms, hostClusterMatcher{m}) 168 case hostIdx: 169 ms = append(ms, hostHostMatcher{m}) 170 } 171 } 172 173 switch len(ms) { 174 case 0: 175 return nil, nil 176 case 1: 177 return ms[0], nil 178 default: 179 return newAndHostMatcher(ms[0], ms[1], ms[2:]...), nil 180 } 181 } 182 183 func parseVMInclude(include string) (VMMatcher, error) { 184 if !isIncludeFormatValid(include) { 185 return nil, fmt.Errorf("bad include format: %s", include) 186 } 187 188 include = cleanInclude(include) 189 parts := strings.Split(include, "/") // /dc/clusterIdx/hostIdx/vmIdx 190 var ms []VMMatcher 191 192 for i, v := range parts { 193 m, err := parseSubInclude(v) 194 if err != nil { 195 return nil, err 196 } 197 switch i { 198 case datacenterIdx: 199 ms = append(ms, vmDCMatcher{m}) 200 case clusterIdx: 201 ms = append(ms, vmClusterMatcher{m}) 202 case hostIdx: 203 ms = append(ms, vmHostMatcher{m}) 204 case vmIdx: 205 ms = append(ms, vmVMMatcher{m}) 206 } 207 } 208 209 switch len(ms) { 210 case 0: 211 return nil, nil 212 case 1: 213 return ms[0], nil 214 default: 215 return newAndVMMatcher(ms[0], ms[1], ms[2:]...), nil 216 } 217 } 218 219 func parseSubInclude(sub string) (matcher.Matcher, error) { 220 sub = strings.TrimSpace(sub) 221 if sub == "" || sub == "!*" { 222 return matcher.FALSE(), nil 223 } 224 if sub == "*" { 225 return matcher.TRUE(), nil 226 } 227 return matcher.NewSimplePatternsMatcher(sub) 228 } 229 230 func isIncludeFormatValid(line string) bool { 231 return strings.HasPrefix(line, "/") 232 }