Skip to content

Commit 29d86d3

Browse files
authored
Adds support for the 'in' filter to slcli call-api (softlayer#728)
* Adds support for the 'in' filter to slcli call-api * Adds support for the 'in' filter to slcli call-api * Adds more tests * Fix small style issue * Add IN operation for `slcli call-api` filters * Fixes linting issues * Fixes linting issues * Fixes linting issues
1 parent 4ffe956 commit 29d86d3

2 files changed

Lines changed: 75 additions & 4 deletions

File tree

SoftLayer/CLI/call_api.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
import click
33

44
from SoftLayer.CLI import environment
5+
from SoftLayer.CLI import exceptions
56
from SoftLayer.CLI import formatting
67
from SoftLayer.CLI import helpers
78
from SoftLayer import utils
89

10+
SPLIT_TOKENS = [
11+
('in', ' IN '),
12+
('eq', '='),
13+
]
14+
915

1016
def _build_filters(_filters):
1117
"""Builds filters using the filter options passed into the CLI.
@@ -14,17 +20,35 @@ def _build_filters(_filters):
1420
"""
1521
root = utils.NestedDict({})
1622
for _filter in _filters:
17-
# split "some.key=value" into ["some.key", "value"]
18-
key, value = _filter.split('=', 1)
19-
23+
operation = None
24+
for operation, token in SPLIT_TOKENS:
25+
# split "some.key=value" into ["some.key", "value"]
26+
top_parts = _filter.split(token, 1)
27+
if len(top_parts) == 2:
28+
break
29+
else:
30+
raise exceptions.CLIAbort('Failed to find valid operation for: %s'
31+
% _filter)
32+
33+
key, value = top_parts
2034
current = root
2135
# split "some.key" into ["some", "key"]
2236
parts = [part.strip() for part in key.split('.')]
2337

2438
# Actually drill down and add the filter
2539
for part in parts[:-1]:
2640
current = current[part]
27-
current[parts[-1]] = utils.query_filter(value.strip())
41+
42+
if operation == 'eq':
43+
current[parts[-1]] = utils.query_filter(value.strip())
44+
elif operation == 'in':
45+
current[parts[-1]] = {
46+
'operation': 'in',
47+
'options': [{
48+
'name': 'data',
49+
'value': [p.strip() for p in value.split(',')],
50+
}],
51+
}
2852

2953
return root.to_dict()
3054

@@ -74,6 +98,8 @@ def cli(env, service, method, parameters, _id, _filters, mask, limit, offset,
7498
-f 'virtualGuests.datacenter.name=dal05' \\
7599
-f 'virtualGuests.maxCpu=4' \\
76100
--mask=id,hostname,datacenter.name,maxCpu
101+
slcli call-api Account getVirtualGuests \\
102+
-f 'virtualGuests.datacenter.name IN dal05,sng01'
77103
"""
78104

79105
args = [service, method] + list(parameters)

tests/CLI/modules/call_api_tests.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import json
88

99
from SoftLayer.CLI import call_api
10+
from SoftLayer.CLI import exceptions
1011
from SoftLayer import testing
1112

13+
import pytest
14+
1215

1316
class BuildFilterTests(testing.TestCase):
1417

@@ -30,6 +33,48 @@ def test_multi(self):
3033
'prop2': {'operation': '_= prop2'},
3134
}
3235

36+
def test_in(self):
37+
result = call_api._build_filters(['prop IN value1,value2'])
38+
assert result == {
39+
'prop': {
40+
'operation': 'in',
41+
'options': [{'name': 'data', 'value': ['value1', 'value2']}],
42+
}
43+
}
44+
45+
def test_in_multi(self):
46+
result = call_api._build_filters([
47+
'prop_a IN a_val1,a_val2',
48+
'prop_b IN b_val1,b_val2',
49+
])
50+
assert result == {
51+
'prop_a': {
52+
'operation': 'in',
53+
'options': [{'name': 'data', 'value': ['a_val1', 'a_val2']}],
54+
},
55+
'prop_b': {
56+
'operation': 'in',
57+
'options': [{'name': 'data', 'value': ['b_val1', 'b_val2']}],
58+
},
59+
}
60+
61+
def test_in_with_whitespace(self):
62+
result = call_api._build_filters(['prop IN value1 , value2 '])
63+
assert result == {
64+
'prop': {
65+
'operation': 'in',
66+
'options': [{'name': 'data', 'value': ['value1', 'value2']}],
67+
}
68+
}
69+
70+
def test_invalid_operation(self):
71+
with pytest.raises(exceptions.CLIAbort):
72+
call_api._build_filters(['prop N/A value1'])
73+
74+
def test_only_whitespace(self):
75+
with pytest.raises(exceptions.CLIAbort):
76+
call_api._build_filters([' '])
77+
3378

3479
class CallCliTests(testing.TestCase):
3580

0 commit comments

Comments
 (0)