Skip to content

Commit a2600b9

Browse files
authored
Merge pull request #2071 from mfranczy/extend-comparison-operators
Add new comparison operators
2 parents 60fc5e0 + 7ff00b3 commit a2600b9

File tree

4 files changed

+61
-22
lines changed

4 files changed

+61
-22
lines changed

api/nfd/v1alpha1/types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,31 @@ const (
329329
// Both the input and value must be integer numbers, otherwise an error is
330330
// returned.
331331
MatchGt MatchOp = "Gt"
332+
// MatchGe returns true if the input is greater than or equal to the value of the
333+
// expression (number of values in the expression must be exactly one).
334+
// Both the input and value must be integer numbers, otherwise an error is
335+
// returned.
336+
MatchGe MatchOp = "Ge"
332337
// MatchLt returns true if the input is less than the value of the
333338
// expression (number of values in the expression must be exactly one).
334339
// Both the input and value must be integer numbers, otherwise an error is
335340
// returned.
336341
MatchLt MatchOp = "Lt"
342+
// MatchLe returns true if the input is less than or equal to the value of the
343+
// expression (number of values in the expression must be exactly one).
344+
// Both the input and value must be integer numbers, otherwise an error is
345+
// returned.
346+
MatchLe MatchOp = "Le"
337347
// MatchGtLt returns true if the input is between two values, i.e. greater
338348
// than the first value and less than the second value of the expression
339349
// (number of values in the expression must be exactly two). Both the input
340350
// and values must be integer numbers, otherwise an error is returned.
341351
MatchGtLt MatchOp = "GtLt"
352+
// MatchGeLe returns true if the input is between two values including the boundary values,
353+
// i.e. greater than or equal to the first value and less than or equal to the second value
354+
// of the expression (number of values in the expression must be exactly two). Both the input
355+
// and values must be integer numbers, otherwise an error is returned.
356+
MatchGeLe MatchOp = "GeLe"
342357
// MatchIsTrue returns true if the input holds the value "true". The
343358
// expression must not have any values.
344359
MatchIsTrue MatchOp = "IsTrue"

docs/usage/customization-guide.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,11 @@ below.
809809
| `Exists` | 0 | The key exists |
810810
| `DoesNotExist` | 0 | The key does not exists |
811811
| `Gt` | 1 | Input is greater than the value. Both the input and value must be integer numbers. |
812+
| `Ge` | 1 | Input is greater than or equal to the value. Both the input and value must be integer numbers. |
812813
| `Lt` | 1 | Input is less than the value. Both the input and value must be integer numbers. |
814+
| `Le` | 1 | Input is less than or equal to the value. Both the input and value must be integer numbers. |
813815
| `GtLt` | 2 | Input is between two values. Both the input and value must be integer numbers. |
816+
| `GeLe` | 2 | Input falls within a range that includes the boundary values. Both the input and value must be integer numbers. |
814817
| `IsTrue` | 0 | Input is equal to "true" |
815818
| `IsFalse` | 0 | Input is equal "false" |
816819

@@ -968,7 +971,7 @@ The following features are available for matching:
968971
| | | **`enabled`** | bool | `true` if swap partition detected, `false` otherwise |
969972
| **`memory.hugepages`** | attribute | | | Discovery of supported huge pages size on node |
970973
| | | **`enabled`** | bool | `true` if total number of huge pages (of any page size) have been configured, otherwise `false` |
971-
| | | **`hugepages-<page-size>`** | string | total number of huge pages (e.g., `hugepages-1Gi=16`) |
974+
| | | **`hugepages-<page-size>`** | string | Total number of huge pages (e.g., `hugepages-1Gi=16`) |
972975
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
973976
| | | **`name`** | string | Name of the network interface |
974977
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |

pkg/apis/nfd/nodefeaturerule/expression.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ var matchOps = map[nfdv1alpha1.MatchOp]struct{}{
4646
nfdv1alpha1.MatchExists: {},
4747
nfdv1alpha1.MatchDoesNotExist: {},
4848
nfdv1alpha1.MatchGt: {},
49+
nfdv1alpha1.MatchGe: {},
4950
nfdv1alpha1.MatchLt: {},
51+
nfdv1alpha1.MatchLe: {},
5052
nfdv1alpha1.MatchGtLt: {},
53+
nfdv1alpha1.MatchGeLe: {},
5154
nfdv1alpha1.MatchIsTrue: {},
5255
nfdv1alpha1.MatchIsFalse: {},
5356
}
@@ -115,7 +118,7 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
115118
return true, nil
116119
}
117120
}
118-
case nfdv1alpha1.MatchGt, nfdv1alpha1.MatchLt:
121+
case nfdv1alpha1.MatchGt, nfdv1alpha1.MatchGe, nfdv1alpha1.MatchLt, nfdv1alpha1.MatchLe:
119122
if len(m.Value) != 1 {
120123
return false, fmt.Errorf("invalid expression, 'value' field must contain exactly one element for Op %q (have %v)", m.Op, m.Value)
121124
}
@@ -129,10 +132,11 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
129132
return false, fmt.Errorf("not a number %q in %v", m.Value[0], m)
130133
}
131134

132-
if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l > r && m.Op == nfdv1alpha1.MatchGt) {
135+
if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l <= r && m.Op == nfdv1alpha1.MatchLe) ||
136+
(l > r && m.Op == nfdv1alpha1.MatchGt) || (l >= r && m.Op == nfdv1alpha1.MatchGe) {
133137
return true, nil
134138
}
135-
case nfdv1alpha1.MatchGtLt:
139+
case nfdv1alpha1.MatchGtLt, nfdv1alpha1.MatchGeLe:
136140
if len(m.Value) != 2 {
137141
return false, fmt.Errorf("invalid expression, value' field must contain exactly two elements for Op %q (have %v)", m.Op, m.Value)
138142
}
@@ -150,7 +154,8 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
150154
if lr[0] >= lr[1] {
151155
return false, fmt.Errorf("invalid expression, value[0] must be less than Value[1] for Op %q (have %v)", m.Op, m.Value)
152156
}
153-
return v > lr[0] && v < lr[1], nil
157+
return (v > lr[0] && v < lr[1] && m.Op == nfdv1alpha1.MatchGtLt) ||
158+
(v >= lr[0] && v <= lr[1] && m.Op == nfdv1alpha1.MatchGeLe), nil
154159
case nfdv1alpha1.MatchIsTrue:
155160
if len(m.Value) != 0 {
156161
return false, fmt.Errorf("invalid expression, 'value' field must be empty for Op %q (have %v)", m.Op, m.Value)

pkg/apis/nfd/nodefeaturerule/expression_test.go

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -232,23 +232,39 @@ func TestEvaluateMatchExpressionValues(t *testing.T) {
232232
{name: "17", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil},
233233
{name: "18", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
234234

235-
{name: "19", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
236-
{name: "20", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil},
237-
{name: "21", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
238-
{name: "22", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
239-
240-
{name: "23", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
241-
{name: "24", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil},
242-
{name: "25", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
243-
{name: "26", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
244-
{name: "27", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
245-
246-
{name: "28", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil},
247-
{name: "29", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil},
248-
{name: "30", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil},
249-
250-
{name: "31", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil},
251-
{name: "32", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil},
235+
{name: "19", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil},
236+
{name: "20", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.True, err: assert.Nil},
237+
{name: "21", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil},
238+
{name: "22", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
239+
240+
{name: "23", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
241+
{name: "24", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil},
242+
{name: "25", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
243+
{name: "26", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
244+
245+
{name: "27", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
246+
{name: "28", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil},
247+
{name: "29", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
248+
{name: "30", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
249+
250+
{name: "31", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
251+
{name: "32", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil},
252+
{name: "33", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
253+
{name: "34", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
254+
{name: "35", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
255+
256+
{name: "36", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
257+
{name: "37", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "-10", "foo": "10"}, result: assert.True, err: assert.Nil},
258+
{name: "38", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
259+
{name: "39", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
260+
{name: "40", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
261+
262+
{name: "41", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil},
263+
{name: "42", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil},
264+
{name: "43", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil},
265+
266+
{name: "44", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil},
267+
{name: "45", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil},
252268
}
253269

254270
for _, tc := range tcs {

0 commit comments

Comments
 (0)