mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-16 21:38:23 +00:00
Merge pull request #2071 from mfranczy/extend-comparison-operators
Add new comparison operators
This commit is contained in:
commit
a2600b9f0f
4 changed files with 58 additions and 19 deletions
|
@ -329,16 +329,31 @@ const (
|
||||||
// Both the input and value must be integer numbers, otherwise an error is
|
// Both the input and value must be integer numbers, otherwise an error is
|
||||||
// returned.
|
// returned.
|
||||||
MatchGt MatchOp = "Gt"
|
MatchGt MatchOp = "Gt"
|
||||||
|
// MatchGe returns true if the input is greater than or equal to the value of the
|
||||||
|
// expression (number of values in the expression must be exactly one).
|
||||||
|
// Both the input and value must be integer numbers, otherwise an error is
|
||||||
|
// returned.
|
||||||
|
MatchGe MatchOp = "Ge"
|
||||||
// MatchLt returns true if the input is less than the value of the
|
// MatchLt returns true if the input is less than the value of the
|
||||||
// expression (number of values in the expression must be exactly one).
|
// expression (number of values in the expression must be exactly one).
|
||||||
// Both the input and value must be integer numbers, otherwise an error is
|
// Both the input and value must be integer numbers, otherwise an error is
|
||||||
// returned.
|
// returned.
|
||||||
MatchLt MatchOp = "Lt"
|
MatchLt MatchOp = "Lt"
|
||||||
|
// MatchLe returns true if the input is less than or equal to the value of the
|
||||||
|
// expression (number of values in the expression must be exactly one).
|
||||||
|
// Both the input and value must be integer numbers, otherwise an error is
|
||||||
|
// returned.
|
||||||
|
MatchLe MatchOp = "Le"
|
||||||
// MatchGtLt returns true if the input is between two values, i.e. greater
|
// MatchGtLt returns true if the input is between two values, i.e. greater
|
||||||
// than the first value and less than the second value of the expression
|
// than the first value and less than the second value of the expression
|
||||||
// (number of values in the expression must be exactly two). Both the input
|
// (number of values in the expression must be exactly two). Both the input
|
||||||
// and values must be integer numbers, otherwise an error is returned.
|
// and values must be integer numbers, otherwise an error is returned.
|
||||||
MatchGtLt MatchOp = "GtLt"
|
MatchGtLt MatchOp = "GtLt"
|
||||||
|
// MatchGeLe returns true if the input is between two values including the boundary values,
|
||||||
|
// i.e. greater than or equal to the first value and less than or equal to the second value
|
||||||
|
// of the expression (number of values in the expression must be exactly two). Both the input
|
||||||
|
// and values must be integer numbers, otherwise an error is returned.
|
||||||
|
MatchGeLe MatchOp = "GeLe"
|
||||||
// MatchIsTrue returns true if the input holds the value "true". The
|
// MatchIsTrue returns true if the input holds the value "true". The
|
||||||
// expression must not have any values.
|
// expression must not have any values.
|
||||||
MatchIsTrue MatchOp = "IsTrue"
|
MatchIsTrue MatchOp = "IsTrue"
|
||||||
|
|
|
@ -809,8 +809,11 @@ below.
|
||||||
| `Exists` | 0 | The key exists |
|
| `Exists` | 0 | The key exists |
|
||||||
| `DoesNotExist` | 0 | The key does not exists |
|
| `DoesNotExist` | 0 | The key does not exists |
|
||||||
| `Gt` | 1 | Input is greater than the value. Both the input and value must be integer numbers. |
|
| `Gt` | 1 | Input is greater than the value. Both the input and value must be integer numbers. |
|
||||||
|
| `Ge` | 1 | Input is greater than or equal to the value. Both the input and value must be integer numbers. |
|
||||||
| `Lt` | 1 | Input is less than the value. Both the input and value must be integer numbers. |
|
| `Lt` | 1 | Input is less than the value. Both the input and value must be integer numbers. |
|
||||||
|
| `Le` | 1 | Input is less than or equal to the value. Both the input and value must be integer numbers. |
|
||||||
| `GtLt` | 2 | Input is between two values. Both the input and value must be integer numbers. |
|
| `GtLt` | 2 | Input is between two values. Both the input and value must be integer numbers. |
|
||||||
|
| `GeLe` | 2 | Input falls within a range that includes the boundary values. Both the input and value must be integer numbers. |
|
||||||
| `IsTrue` | 0 | Input is equal to "true" |
|
| `IsTrue` | 0 | Input is equal to "true" |
|
||||||
| `IsFalse` | 0 | Input is equal "false" |
|
| `IsFalse` | 0 | Input is equal "false" |
|
||||||
|
|
||||||
|
@ -968,7 +971,7 @@ The following features are available for matching:
|
||||||
| | | **`enabled`** | bool | `true` if swap partition detected, `false` otherwise |
|
| | | **`enabled`** | bool | `true` if swap partition detected, `false` otherwise |
|
||||||
| **`memory.hugepages`** | attribute | | | Discovery of supported huge pages size on node |
|
| **`memory.hugepages`** | attribute | | | Discovery of supported huge pages size on node |
|
||||||
| | | **`enabled`** | bool | `true` if total number of huge pages (of any page size) have been configured, otherwise `false` |
|
| | | **`enabled`** | bool | `true` if total number of huge pages (of any page size) have been configured, otherwise `false` |
|
||||||
| | | **`hugepages-<page-size>`** | string | total number of huge pages (e.g., `hugepages-1Gi=16`) |
|
| | | **`hugepages-<page-size>`** | string | Total number of huge pages (e.g., `hugepages-1Gi=16`) |
|
||||||
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
|
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
|
||||||
| | | **`name`** | string | Name of the network interface |
|
| | | **`name`** | string | Name of the network interface |
|
||||||
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |
|
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |
|
||||||
|
|
|
@ -46,8 +46,11 @@ var matchOps = map[nfdv1alpha1.MatchOp]struct{}{
|
||||||
nfdv1alpha1.MatchExists: {},
|
nfdv1alpha1.MatchExists: {},
|
||||||
nfdv1alpha1.MatchDoesNotExist: {},
|
nfdv1alpha1.MatchDoesNotExist: {},
|
||||||
nfdv1alpha1.MatchGt: {},
|
nfdv1alpha1.MatchGt: {},
|
||||||
|
nfdv1alpha1.MatchGe: {},
|
||||||
nfdv1alpha1.MatchLt: {},
|
nfdv1alpha1.MatchLt: {},
|
||||||
|
nfdv1alpha1.MatchLe: {},
|
||||||
nfdv1alpha1.MatchGtLt: {},
|
nfdv1alpha1.MatchGtLt: {},
|
||||||
|
nfdv1alpha1.MatchGeLe: {},
|
||||||
nfdv1alpha1.MatchIsTrue: {},
|
nfdv1alpha1.MatchIsTrue: {},
|
||||||
nfdv1alpha1.MatchIsFalse: {},
|
nfdv1alpha1.MatchIsFalse: {},
|
||||||
}
|
}
|
||||||
|
@ -115,7 +118,7 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case nfdv1alpha1.MatchGt, nfdv1alpha1.MatchLt:
|
case nfdv1alpha1.MatchGt, nfdv1alpha1.MatchGe, nfdv1alpha1.MatchLt, nfdv1alpha1.MatchLe:
|
||||||
if len(m.Value) != 1 {
|
if len(m.Value) != 1 {
|
||||||
return false, fmt.Errorf("invalid expression, 'value' field must contain exactly one element for Op %q (have %v)", m.Op, m.Value)
|
return false, fmt.Errorf("invalid expression, 'value' field must contain exactly one element for Op %q (have %v)", m.Op, m.Value)
|
||||||
}
|
}
|
||||||
|
@ -129,10 +132,11 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
|
||||||
return false, fmt.Errorf("not a number %q in %v", m.Value[0], m)
|
return false, fmt.Errorf("not a number %q in %v", m.Value[0], m)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l > r && m.Op == nfdv1alpha1.MatchGt) {
|
if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l <= r && m.Op == nfdv1alpha1.MatchLe) ||
|
||||||
|
(l > r && m.Op == nfdv1alpha1.MatchGt) || (l >= r && m.Op == nfdv1alpha1.MatchGe) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
case nfdv1alpha1.MatchGtLt:
|
case nfdv1alpha1.MatchGtLt, nfdv1alpha1.MatchGeLe:
|
||||||
if len(m.Value) != 2 {
|
if len(m.Value) != 2 {
|
||||||
return false, fmt.Errorf("invalid expression, value' field must contain exactly two elements for Op %q (have %v)", m.Op, m.Value)
|
return false, fmt.Errorf("invalid expression, value' field must contain exactly two elements for Op %q (have %v)", m.Op, m.Value)
|
||||||
}
|
}
|
||||||
|
@ -150,7 +154,8 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i
|
||||||
if lr[0] >= lr[1] {
|
if lr[0] >= lr[1] {
|
||||||
return false, fmt.Errorf("invalid expression, value[0] must be less than Value[1] for Op %q (have %v)", m.Op, m.Value)
|
return false, fmt.Errorf("invalid expression, value[0] must be less than Value[1] for Op %q (have %v)", m.Op, m.Value)
|
||||||
}
|
}
|
||||||
return v > lr[0] && v < lr[1], nil
|
return (v > lr[0] && v < lr[1] && m.Op == nfdv1alpha1.MatchGtLt) ||
|
||||||
|
(v >= lr[0] && v <= lr[1] && m.Op == nfdv1alpha1.MatchGeLe), nil
|
||||||
case nfdv1alpha1.MatchIsTrue:
|
case nfdv1alpha1.MatchIsTrue:
|
||||||
if len(m.Value) != 0 {
|
if len(m.Value) != 0 {
|
||||||
return false, fmt.Errorf("invalid expression, 'value' field must be empty for Op %q (have %v)", m.Op, m.Value)
|
return false, fmt.Errorf("invalid expression, 'value' field must be empty for Op %q (have %v)", m.Op, m.Value)
|
||||||
|
|
|
@ -232,23 +232,39 @@ func TestEvaluateMatchExpressionValues(t *testing.T) {
|
||||||
{name: "17", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil},
|
{name: "17", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil},
|
||||||
{name: "18", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
{name: "18", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
|
|
||||||
{name: "19", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
{name: "19", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil},
|
||||||
{name: "20", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil},
|
{name: "20", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.True, err: assert.Nil},
|
||||||
{name: "21", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
{name: "21", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil},
|
||||||
{name: "22", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
{name: "22", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
|
|
||||||
{name: "23", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
{name: "23", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
||||||
{name: "24", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil},
|
{name: "24", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil},
|
||||||
{name: "25", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
|
{name: "25", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
||||||
{name: "26", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
{name: "26", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
{name: "27", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
|
||||||
|
|
||||||
{name: "28", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil},
|
{name: "27", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
||||||
{name: "29", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil},
|
{name: "28", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil},
|
||||||
{name: "30", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil},
|
{name: "29", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
||||||
|
{name: "30", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
|
|
||||||
{name: "31", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil},
|
{name: "31", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
||||||
{name: "32", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil},
|
{name: "32", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "33", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "34", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
||||||
|
{name: "35", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
|
|
||||||
|
{name: "36", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "37", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "-10", "foo": "10"}, result: assert.True, err: assert.Nil},
|
||||||
|
{name: "38", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "39", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil},
|
||||||
|
{name: "40", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil},
|
||||||
|
|
||||||
|
{name: "41", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil},
|
||||||
|
{name: "42", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "43", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil},
|
||||||
|
|
||||||
|
{name: "44", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil},
|
||||||
|
{name: "45", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
|
|
Loading…
Add table
Reference in a new issue