@@ -18,6 +18,8 @@ import (
18
18
"github.com/choria-io/go-choria/internal/util"
19
19
)
20
20
21
+ var validOperators = regexp .MustCompile (`<=|>=|=>|=<|<|>|!=|=~|={1,2}` )
22
+
21
23
// Logger provides logging facilities
22
24
type Logger interface {
23
25
Warnf (format string , args ... any )
@@ -173,18 +175,49 @@ func HasFact(fact string, operator string, value string, file string, log Logger
173
175
}
174
176
175
177
// ParseFactFilterString parses a fact filter string as typically typed on the CLI
176
- func ParseFactFilterString (f string ) (pf [3 ]string , err error ) {
177
- if matched := regexp .MustCompile ("^([^ ]+?)[ ]*=>[ ]*(.+)" ).FindStringSubmatch (f ); len (matched ) > 0 {
178
- return [3 ]string {matched [1 ], ">=" , matched [2 ]}, nil
179
- } else if matched := regexp .MustCompile ("^([^ ]+?)[ ]*=<[ ]*(.+)" ).FindStringSubmatch (f ); len (matched ) > 0 {
180
- return [3 ]string {matched [1 ], "<=" , matched [2 ]}, nil
181
- } else if matched := regexp .MustCompile ("^([^ ]+?)[ ]*(<=|>=|<|>|!=|==|=~)[ ]*(.+)" ).FindStringSubmatch (f ); len (matched ) > 0 {
182
- return [3 ]string {matched [1 ], matched [2 ], matched [3 ]}, nil
183
- } else if matched := regexp .MustCompile ("^(.+?)[ ]*=[ ]*/(.+)/$" ).FindStringSubmatch (f ); len (matched ) > 0 {
184
- return [3 ]string {matched [1 ], "=~" , "/" + matched [2 ] + "/" }, nil
185
- } else if matched := regexp .MustCompile ("^([^= ]+?)[ ]*=[ ]*(.+)" ).FindStringSubmatch (f ); len (matched ) > 0 {
186
- return [3 ]string {matched [1 ], "==" , matched [2 ]}, nil
178
+ func ParseFactFilterString (f string ) ([3 ]string , error ) {
179
+ operatorIndexes := validOperators .FindAllStringIndex (f , - 1 )
180
+ var mainOpIndex []int
181
+
182
+ if opCount := len (operatorIndexes ); opCount > 1 {
183
+ // This is a special case where the left operand contains a valid operator.
184
+ // We skip over everything and use the right most operator.
185
+ mainOpIndex = operatorIndexes [len (operatorIndexes )- 1 ]
186
+ } else if opCount == 1 {
187
+ mainOpIndex = operatorIndexes [0 ]
187
188
} else {
188
189
return [3 ]string {}, fmt .Errorf ("could not parse fact %s it does not appear to be in a valid format" , f )
189
190
}
191
+
192
+ op := f [mainOpIndex [0 ]:mainOpIndex [1 ]]
193
+ leftOp := strings .TrimSpace (f [:mainOpIndex [0 ]])
194
+ rightOp := strings .TrimSpace (f [mainOpIndex [1 ]:])
195
+
196
+ // validate that the left and right operands are both valid
197
+ if len (leftOp ) == 0 || len (rightOp ) == 0 {
198
+ return [3 ]string {}, fmt .Errorf ("could not parse fact %s it does not appear to be in a valid format" , f )
199
+ }
200
+
201
+ lStartString := string (leftOp [0 ])
202
+ rEndString := string (rightOp [len (rightOp )- 1 ])
203
+ if validOperators .MatchString (lStartString ) || validOperators .Match ([]byte (rEndString )) {
204
+ return [3 ]string {}, fmt .Errorf ("could not parse fact %s it does not appear to be in a valid format" , f )
205
+ }
206
+
207
+ // transform op and value for processing
208
+ switch op {
209
+ case "=" :
210
+ op = "=="
211
+ case "=<" :
212
+ op = "<="
213
+ case "=>" :
214
+ op = ">="
215
+ }
216
+
217
+ // finally check for old style regex fact matches
218
+ if rightOp [0 ] == '/' && rightOp [len (rightOp )- 1 ] == '/' {
219
+ op = "=~"
220
+ }
221
+
222
+ return [3 ]string {leftOp , op , rightOp }, nil
190
223
}
0 commit comments