From 6d6ecb97ea18bdbb9f80fd1fda02991b30e80b13 Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Wed, 25 May 2016 16:38:31 -0500 Subject: [PATCH 1/8] Adds support for the 'in' filter to slcli call-api --- SoftLayer/CLI/call_api.py | 16 +++++++++++++++- tests/CLI/modules/call_api_tests.py | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/SoftLayer/CLI/call_api.py b/SoftLayer/CLI/call_api.py index 31b0a76c3..a5195fb87 100644 --- a/SoftLayer/CLI/call_api.py +++ b/SoftLayer/CLI/call_api.py @@ -24,7 +24,19 @@ def _build_filters(_filters): # Actually drill down and add the filter for part in parts[:-1]: current = current[part] - current[parts[-1]] = utils.query_filter(value.strip()) + + value = value + if ',' in value: + value_parts = value.split(',') + current[parts[-1]] = { + 'operation': 'in', + 'options': [{ + 'name': 'data', + 'value': [p.strip() for p in value_parts], + }], + } + else: + current[parts[-1]] = utils.query_filter(value.strip()) return root.to_dict() @@ -74,6 +86,8 @@ def cli(env, service, method, parameters, _id, _filters, mask, limit, offset, -f 'virtualGuests.datacenter.name=dal05' \\ -f 'virtualGuests.maxCpu=4' \\ --mask=id,hostname,datacenter.name,maxCpu + slcli call-api Account getVirtualGuests \\ + -f 'virtualGuests.datacenter.name=dal05,sng01' """ args = [service, method] + list(parameters) diff --git a/tests/CLI/modules/call_api_tests.py b/tests/CLI/modules/call_api_tests.py index 84dd69016..67ce3c141 100644 --- a/tests/CLI/modules/call_api_tests.py +++ b/tests/CLI/modules/call_api_tests.py @@ -30,6 +30,12 @@ def test_multi(self): 'prop2': {'operation': '_= prop2'}, } + def test_in(self): + result = call_api._build_filters(['prop=value1,value2']) + assert result == { + 'prop': {'operation': 'in', 'options': [{'name': 'data', 'value': ['value1', 'value2']}]} + } + class CallCliTests(testing.TestCase): From a41e530dfaf7e1f8a828967b98cd07f6e7b0cfdd Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Wed, 25 May 2016 16:39:49 -0500 Subject: [PATCH 2/8] Adds support for the 'in' filter to slcli call-api --- tests/CLI/modules/call_api_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/CLI/modules/call_api_tests.py b/tests/CLI/modules/call_api_tests.py index 67ce3c141..114ede830 100644 --- a/tests/CLI/modules/call_api_tests.py +++ b/tests/CLI/modules/call_api_tests.py @@ -33,7 +33,10 @@ def test_multi(self): def test_in(self): result = call_api._build_filters(['prop=value1,value2']) assert result == { - 'prop': {'operation': 'in', 'options': [{'name': 'data', 'value': ['value1', 'value2']}]} + 'prop': { + 'operation': 'in', + 'options': [{'name': 'data', 'value': ['value1', 'value2']}], + } } From feec34f66f4be9559ffcfda9ad10fa781e086c29 Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Wed, 25 May 2016 16:50:59 -0500 Subject: [PATCH 3/8] Adds more tests --- tests/CLI/modules/call_api_tests.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/CLI/modules/call_api_tests.py b/tests/CLI/modules/call_api_tests.py index 114ede830..c0bd5a6f5 100644 --- a/tests/CLI/modules/call_api_tests.py +++ b/tests/CLI/modules/call_api_tests.py @@ -39,6 +39,31 @@ def test_in(self): } } + def test_in_multi(self): + result = call_api._build_filters([ + 'prop_a=a_val1,a_val2', + 'prop_b=b_val1,b_val2', + ]) + assert result == { + 'prop_a': { + 'operation': 'in', + 'options': [{'name': 'data', 'value': ['a_val1', 'a_val2']}], + }, + 'prop_b': { + 'operation': 'in', + 'options': [{'name': 'data', 'value': ['b_val1', 'b_val2']}], + }, + } + + def test_in_with_whitespace(self): + result = call_api._build_filters(['prop= value1 , value2 ']) + assert result == { + 'prop': { + 'operation': 'in', + 'options': [{'name': 'data', 'value': ['value1', 'value2']}], + } + } + class CallCliTests(testing.TestCase): From 933d3a7b90ac11cf9d195b2bf32381f086f0606d Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Wed, 25 May 2016 16:53:31 -0500 Subject: [PATCH 4/8] Fix small style issue --- tests/CLI/modules/call_api_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/CLI/modules/call_api_tests.py b/tests/CLI/modules/call_api_tests.py index c0bd5a6f5..9a51af260 100644 --- a/tests/CLI/modules/call_api_tests.py +++ b/tests/CLI/modules/call_api_tests.py @@ -41,8 +41,8 @@ def test_in(self): def test_in_multi(self): result = call_api._build_filters([ - 'prop_a=a_val1,a_val2', - 'prop_b=b_val1,b_val2', + 'prop_a=a_val1,a_val2', + 'prop_b=b_val1,b_val2', ]) assert result == { 'prop_a': { From b7436f0a2dd828ba2e3177bb1db99c88b6ebe647 Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Thu, 23 Jun 2016 17:31:28 -0500 Subject: [PATCH 5/8] Add IN operation for `slcli call-api` filters --- SoftLayer/CLI/call_api.py | 26 +++++++++++++++++++------- tests/CLI/modules/call_api_tests.py | 19 +++++++++++++++---- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/SoftLayer/CLI/call_api.py b/SoftLayer/CLI/call_api.py index a5195fb87..a33642c90 100644 --- a/SoftLayer/CLI/call_api.py +++ b/SoftLayer/CLI/call_api.py @@ -2,10 +2,16 @@ import click from SoftLayer.CLI import environment +from SoftLayer.CLI import exceptions from SoftLayer.CLI import formatting from SoftLayer.CLI import helpers from SoftLayer import utils +SPLIT_TOKENS = [ + ('in', ' IN '), + ('eq', '='), +] + def _build_filters(_filters): """Builds filters using the filter options passed into the CLI. @@ -14,9 +20,16 @@ def _build_filters(_filters): """ root = utils.NestedDict({}) for _filter in _filters: - # split "some.key=value" into ["some.key", "value"] - key, value = _filter.split('=', 1) + for op, token in SPLIT_TOKENS: + # split "some.key=value" into ["some.key", "value"] + top_parts = _filter.split(token, 1) + operation = op + if len(top_parts) == 2: + break + else: + raise exceptions.CLIAbort('Failed to find valid operation for: %s' % _filter) + key, value = top_parts current = root # split "some.key" into ["some", "key"] parts = [part.strip() for part in key.split('.')] @@ -25,8 +38,9 @@ def _build_filters(_filters): for part in parts[:-1]: current = current[part] - value = value - if ',' in value: + if operation == 'eq': + current[parts[-1]] = utils.query_filter(value.strip()) + elif operation == 'in': value_parts = value.split(',') current[parts[-1]] = { 'operation': 'in', @@ -35,8 +49,6 @@ def _build_filters(_filters): 'value': [p.strip() for p in value_parts], }], } - else: - current[parts[-1]] = utils.query_filter(value.strip()) return root.to_dict() @@ -87,7 +99,7 @@ def cli(env, service, method, parameters, _id, _filters, mask, limit, offset, -f 'virtualGuests.maxCpu=4' \\ --mask=id,hostname,datacenter.name,maxCpu slcli call-api Account getVirtualGuests \\ - -f 'virtualGuests.datacenter.name=dal05,sng01' + -f 'virtualGuests.datacenter.name IN dal05,sng01' """ args = [service, method] + list(parameters) diff --git a/tests/CLI/modules/call_api_tests.py b/tests/CLI/modules/call_api_tests.py index 9a51af260..a6ce0d767 100644 --- a/tests/CLI/modules/call_api_tests.py +++ b/tests/CLI/modules/call_api_tests.py @@ -7,8 +7,11 @@ import json from SoftLayer.CLI import call_api +from SoftLayer.CLI import exceptions from SoftLayer import testing +import pytest + class BuildFilterTests(testing.TestCase): @@ -31,7 +34,7 @@ def test_multi(self): } def test_in(self): - result = call_api._build_filters(['prop=value1,value2']) + result = call_api._build_filters(['prop IN value1,value2']) assert result == { 'prop': { 'operation': 'in', @@ -41,8 +44,8 @@ def test_in(self): def test_in_multi(self): result = call_api._build_filters([ - 'prop_a=a_val1,a_val2', - 'prop_b=b_val1,b_val2', + 'prop_a IN a_val1,a_val2', + 'prop_b IN b_val1,b_val2', ]) assert result == { 'prop_a': { @@ -56,7 +59,7 @@ def test_in_multi(self): } def test_in_with_whitespace(self): - result = call_api._build_filters(['prop= value1 , value2 ']) + result = call_api._build_filters(['prop IN value1 , value2 ']) assert result == { 'prop': { 'operation': 'in', @@ -64,6 +67,14 @@ def test_in_with_whitespace(self): } } + def test_invalid_operation(self): + with pytest.raises(exceptions.CLIAbort): + call_api._build_filters(['prop N/A value1']) + + def test_only_whitespace(self): + with pytest.raises(exceptions.CLIAbort): + call_api._build_filters([' ']) + class CallCliTests(testing.TestCase): From 3e359198c50f51befb8c5850ea47675547aabcae Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Tue, 23 Aug 2016 21:24:24 -0500 Subject: [PATCH 6/8] Fixes linting issues --- SoftLayer/CLI/call_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SoftLayer/CLI/call_api.py b/SoftLayer/CLI/call_api.py index a33642c90..39b604eeb 100644 --- a/SoftLayer/CLI/call_api.py +++ b/SoftLayer/CLI/call_api.py @@ -20,14 +20,14 @@ def _build_filters(_filters): """ root = utils.NestedDict({}) for _filter in _filters: - for op, token in SPLIT_TOKENS: + for operation, token in SPLIT_TOKENS: # split "some.key=value" into ["some.key", "value"] top_parts = _filter.split(token, 1) - operation = op if len(top_parts) == 2: break else: - raise exceptions.CLIAbort('Failed to find valid operation for: %s' % _filter) + raise exceptions.CLIAbort('Failed to find valid operation for: %s' + % _filter) key, value = top_parts current = root From 800e9b2380ac356e861f2373d16478bda55f2d8b Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Tue, 23 Aug 2016 21:27:56 -0500 Subject: [PATCH 7/8] Fixes linting issues --- SoftLayer/CLI/call_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/SoftLayer/CLI/call_api.py b/SoftLayer/CLI/call_api.py index 39b604eeb..a9ca6e823 100644 --- a/SoftLayer/CLI/call_api.py +++ b/SoftLayer/CLI/call_api.py @@ -20,6 +20,7 @@ def _build_filters(_filters): """ root = utils.NestedDict({}) for _filter in _filters: + operation = None for operation, token in SPLIT_TOKENS: # split "some.key=value" into ["some.key", "value"] top_parts = _filter.split(token, 1) From 399cb8e1e738149bb1736cafa468f70d2a5f6634 Mon Sep 17 00:00:00 2001 From: Kevin McDonald Date: Tue, 23 Aug 2016 21:35:05 -0500 Subject: [PATCH 8/8] Fixes linting issues --- SoftLayer/CLI/call_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SoftLayer/CLI/call_api.py b/SoftLayer/CLI/call_api.py index a9ca6e823..0adb4fa31 100644 --- a/SoftLayer/CLI/call_api.py +++ b/SoftLayer/CLI/call_api.py @@ -42,12 +42,11 @@ def _build_filters(_filters): if operation == 'eq': current[parts[-1]] = utils.query_filter(value.strip()) elif operation == 'in': - value_parts = value.split(',') current[parts[-1]] = { 'operation': 'in', 'options': [{ 'name': 'data', - 'value': [p.strip() for p in value_parts], + 'value': [p.strip() for p in value.split(',')], }], }